Giter Site home page Giter Site logo

Comments (17)

dpc avatar dpc commented on September 25, 2024

Mioco should already by handing panics, by doing an unwind and catching it. Shutdown should kill all the existing coroutines and catch it internally too. If it doesn't work, it's a bug. Do you have any full working example (gist or something), that I could try to reproduce the problem you're experiencing?

I'm open on opinions where to add any more information (or PRs) to documentation too.

from mioco.pre-0.9.

dpc avatar dpc commented on September 25, 2024

For reference: https://github.com/dpc/mioco/blob/master/src/coroutine.rs#L239

        let coroutine_main_fn = move || {
            let coroutine_user_fn = panic::AssertUnwindSafe(coroutine_user_fn);
            let res = panic::catch_unwind(move || {

                let coroutine = unsafe { tl_current_coroutine() };
                if coroutine.killed {
                    panic::resume_unwind(Box::new(Killed))
                }

                coroutine_user_fn()
            });

            let coroutine = unsafe { tl_current_coroutine() };
            coroutine.blocked_on.clear();
            coroutine.self_rc = None;
            coroutine.state = State::Finished;

            let id = coroutine.id;
            {
                let mut handler_shared = coroutine.handler_shared
                                                  .as_ref()
                                                  .unwrap()
                                                  .borrow_mut();
                handler_shared.coroutines.remove(id).unwrap();
                handler_shared.coroutines_dec();
            }

            let config = coroutine.handler_shared().coroutine_config;
            match res {
                Ok(res) => {
                    co_debug!(coroutine, "finished normally");
                    let _ = exit_sender.send(Ok(res));
                }
                Err(cause) => {
                    if config.catch_panics {
                        co_debug!(coroutine, "finished by panick");
                        let _ = exit_sender.send(Err(cause));
                    } else {
                        // send fail here instead with the internal reason,
                        // so the user may get a nice backtrace
                        let handler = coroutine.handler_shared.as_ref().unwrap().borrow();
                        sender_retry(&handler.get_sender_to_own_thread(),
                                     Message::PropagatePanic(cause));
                    }
                }
            }
         };

coroutine_user_fn() runs in panic::catch_unwind block, then the code checks how was the coroutine_user_fn terminated, and sends result through a channel for other threads to receive.

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

Ok, good to know it catches panics. I can add that to the documentation (at least for spawn). I am still at a loss to spawn 2 coroutines and then wait for the first one to finish (both are supposed to run forever) and then call shutdown when either 1 of them finishes. join is blocking, so how do I join multiple coroutines at the same time? It seems like I need to do my own panic catching anyway as per the snippet I gave.

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

I think my issue with not shutting down could be the need to add a sync block. The main documentation states that mioco::sync should be used but this function does not appear to be exported.

from mioco.pre-0.9.

dpc avatar dpc commented on September 25, 2024

sync has been renamed in the master branch due to confict with sync module.

join on coroutine will block only to the end of that coroutine. You can always store JoinHandls in a vector and block one by one on them. mioco::start will return after all coroutines finished, too.

If you could show me full code (without the custom unwind catching) and describe what's the difference between what you expect, and what is actually happening, I could probably help more.

Thanks for PR, much appreciated.

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

I sent #147 to fix sync -> offload documentation. This change seems to be on the 0.7.0 release where I can call it in my program, but I don't see offload in the generated docs.

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

blocking joins one-by-one would not match my use case of stopping all related spawns when one stops. Essentially I want a select on the joins.

Ultimately I want to be able to throw a panic back to the main execution thread to stop the program rather than silently trapping panics in coroutines and not realizing that they occur. But I also want to give each coroutine a chance to gracefully exit by calling mioco::shutdown.

Here is what I came up with for accomplishing this right now: https://github.com/gregwebs/mioco-shutdown/blob/master/src/main.rs

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

This is something more like what I want:

// similar to the normal spawn
// However, if a panic occurs, call `mioco::shutdown`
fn spawn_catch_shutdown <F, T>(f: F)
  where F: FnOnce() -> T, F: std::panic::UnwindSafe, F: Send + 'static, T: Send + 'static
{
    mioco::spawn(|| {
        if let Err(err) = panic::catch_unwind(|| {
          f();
        }) {
          mioco::shutdown();
        }
    } );
}

As a separate issue because I am thinking about having multiple coroutine groups where a group is linked to all fail together (using mioco::start for this right now), I am confused about the behaviour of shutdown. The documentation says that it shuts down the mioco instance, but also suggests calling mioco::spawn to launch it if needed. mioco::start seems to suggest that multiple instances can be running at the same time. Which instance would shutdown stop in that case?

from mioco.pre-0.9.

dpc avatar dpc commented on September 25, 2024

You can have multiple mioco instances. mioco:spawn/mioco::start will spawn a new instance if it was called from outside an existing instance.

Eg.

fn main() {
mioco::spawn(|| { ... });
mioco::spawn(|| { ... });
}

will get you two separate instances of mioco - each will have to shutdown separately. But:

fn main() {
mioco::spawn(|| { 
    mioco::spawn(|| { ... });
    ...
 });

}

will be just one.

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

But if there are 2 instances running, it is not defined which one will shutdown when this code is run?

mioco::spawn(||{mioco::shutdown})

That seems like a buggy edge case

from mioco.pre-0.9.

dpc avatar dpc commented on September 25, 2024

shutdown is supposed to kill the whole instance (all coroutines inside it).

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

But there can be multiple instances. Which instance?

from mioco.pre-0.9.

dpc avatar dpc commented on September 25, 2024

The one that you executed mioco::shutdown() inside of. mioco::spawn creates an instance if it was not executed within one already. If it was, it will just add one more coroutine to it. For reference:
https://github.com/dpc/mioco/blob/master/src/mod.rs#L869

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

But what if 2 instances have been created (with mioco::start)?

from mioco.pre-0.9.

dpc avatar dpc commented on September 25, 2024

Then you need to mioco::shutdown in each of them.

from mioco.pre-0.9.

gregwebs avatar gregwebs commented on September 25, 2024

right, just trying to point out that the API allows for uses with undefined behavior.

I couldn't fix my issue with mioco::offload (The thread makes a blocking call to docker.events(&Default::default());). Glad I could help out with some docs, but I think I will try going back to OS threads for now.

from mioco.pre-0.9.

dpc avatar dpc commented on September 25, 2024

Hmmm... Is it undefined or just not clearly enough explained in the docs?

from mioco.pre-0.9.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.