Giter VIP home page Giter VIP logo

Comments (13)

Escapingbug avatar Escapingbug commented on May 17, 2024 1

The stackoverflow problem is caused by how errors are handled. Currently app::RuntimeError's fmt::Debug implementation has a problem, it uses write!(f, "{:?}", self), which will call itself once and once again.

Since I'm not sure how you want this error be handled, I couldn't fix this problem.

Actually you are right, I was thinking about this when I found this error. We can force exit the thread by drop(maybe? I tried it, and it did quite), but the state will be inconsistent. Maybe we really should let user add some "guardian" to task, so when it is forced to quit, one can do some recovery job(fix some inconsistent state?), or None when no need for that.

I'm also curious about why that Arc::try_unwrap returns error, since I'm not very familiar with the whole structure of the code.

BTW, this is a good repo, maybe it could change the future how rust people write gui applications. Looking forward to helping(although I'm no expert in gui or client-side application area).

from azul.

Escapingbug avatar Escapingbug commented on May 17, 2024 1

I have sent a pull request to fix ArcUnlockError problem. Now we should decide if we should force to exit(just exit main thread, and let OS do sub-threads collection).

from azul.

fschutt avatar fschutt commented on May 17, 2024

Yeah, I know about this, it actually stack overflows, then crashes for some reason. This is a problem that isn't really easy to solve, because the counter is on a background thread and I can't "kill" the background thread - on the other hand I also can't just exit and leave the background thread running.

or kill the thread nicely

That's kind of the problem, this is impossible, due to how threads work on an operating-system level. I can quit the application without cleaning up the threads, but then the problem is that the background thread is still running, so what should I do?

I know about this, added it to the cards here: https://github.com/maps4print/azul/projects/1#card-13479920 - but I am not sure how to actually solve this. As far as I know, you can only kill processes (both on Linux and on Windows), not individual threads.

from azul.

LordZane avatar LordZane commented on May 17, 2024

If you want to "kill" a background thread, create a channel, have the main thread hold an Option, and have the background thread hold the receiver. Each loop iteration of the background thread, it trys receiver.try_recv(), and if that fails due to connection dropped, stops the loop, ending the thread. When you want it to stop, simply replace the Some(Sender) with None on the main thread

from azul.

fschutt avatar fschutt commented on May 17, 2024

@LordZane Yes, but you have to understand that the framework has no control over the thread. The task is written by the application programmer, I can't "pause" the execution of a thread from azul. Only the person who uses azul (i.e. you) can control what happens inside the thread. So you would have to create the channel / write the loop. And that's already possible, the question is what happens when a thread isn't programmed in that way and the application exits all windows - should the data model stay alive or not?

from azul.

LordZane avatar LordZane commented on May 17, 2024

I'm not sure I understand the issue. Once the main thread ends (all window are closed), the OS should cleanup the background threads, no? No manual cleanup should be necessary

from azul.

Escapingbug avatar Escapingbug commented on May 17, 2024

I think I can explain a little bit about this.

The tasks are defined by users, one thread for each task will be run when it starts. But when main thread is trying to exit, all tasks, which are defined by users, not guaranteed to exit right away. Currently, there's even no information transferred to tasks, they don't know that the main thread is exiting, the main thread is only doing threads joining, waiting for their completions.

So, the main thread actually is not ended unless all tasks are completed, using a join.

What we need is to decide what should happen once a user tries to exit before tasks' completion.

Actually, I think it is fine to just end main thread without joining, although this may cause problem. This should be a problem for users to solve.

But how am I getting ArcUnlockError when force exiting?

from azul.

fschutt avatar fschutt commented on May 17, 2024

Yeah I'll investigate the ArcUnlockError tomorrow, that shouldn't happen.

from azul.

Escapingbug avatar Escapingbug commented on May 17, 2024

Ok, I have already done that. It is because that tasks lifetime is not ended when run_inner returns. It actually ends when run is returning. That is to say, when you do that try_unwrap, it is not dropped.

from azul.

fschutt avatar fschutt commented on May 17, 2024

Right, so what I think would be the right decision to solve this:

  1. In the AppConfig I'll make a field if the application should exit if there are still non-main threads running after all windows are closed (via std::process::exit) - and if yes, with what exit code. Exiting destroys the entire process, and therefore the OS can clean up the threads immediately.
  2. Panicking threads / tasks currently crash the entire app. AppConfig should have another field to set if (and how) azul should recover from crashed / poisoned tasks.
  3. The default value (None) should let the tasks running until they finish. This is likely an application error, etc. but it's not the job of the framework to solve that, the application programmer has to solve it gracefully. The Arc<()> that gets passed into the task can be used to check if the main thread has exited. This means that tasks can run longer than the main thread (and an application can still be "running" even though all windows have been closed).
  4. Update the async demo to demonstrate this new behaviour

I.e. something like this:

struct AppConfig { 
     // default: None - don't exit, rather let the threads run
     // if it's Some(x), then `std::process::exit(x)` - so:
     // Some(0) will call exit(0), Some(1) will call exit(1), etc.
    should_exit_after_windows_closed: Option<ExitCode>,
}

from azul.

LordZane avatar LordZane commented on May 17, 2024
  1. Maybe better on a per-task basis? Do exit codes matter? Up to you
  2. Is this necessary? Rust shouldn't crash after all, if there's an error, it should report it as a Result. Again, up to you

from azul.

Escapingbug avatar Escapingbug commented on May 17, 2024
1. Maybe better on a per-task basis? Do exit codes matter? Up to you

2. Is this necessary? Rust shouldn't crash after all, if there's an error, it should report it as a Result. Again, up to you

Agreed.

One task may be slow and not critical while another may be fast but critical. So we still want to wait until critical one to finish but leaving the not critical ones exit immediately. And I also think there should be a way for user to change how we react on windows when a closing event is received. Like, one should be able to "hold up" windows, and prompt some "waiting till _ to complete" message till waiting for background tasks.

And for the thread panicking stuff, it should just panic the whole application, because it represents an error instead of simple exception. That means, critical bugs that prevent the whole application to continue. For example, OOM. Then we really should not recover from these, or else, result should be returned.

from azul.

fschutt avatar fschutt commented on May 17, 2024

Well, these two problems have been fixed now, it doesn't crash anymore, it just closes the window, but the thread is still active. I do think that this would be an acceptable behaviour, because you wouldn't expect the framework to interfere with user code. Maybe there is indeed a task that should run longer than any window is open. So right now, it just closes the window immediately, but doesn't end the process, since the background thread is still running.

I am closing this for now, since the original issue (that the async example crashes / panics) is fixed. Feel free to reopen if you disagree with that choice.

from azul.

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.