Skip to content

Change thread_worker library to propagate panics by default #817

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
matklad opened this issue Feb 13, 2019 · 5 comments · Fixed by #833
Closed

Change thread_worker library to propagate panics by default #817

matklad opened this issue Feb 13, 2019 · 5 comments · Fixed by #833
Assignees
Labels
E-medium fun A technically challenging issue with high impact

Comments

@matklad
Copy link
Member

matklad commented Feb 13, 2019

We have a small thread_worker for spawning background threads. It's main purpose is to force clean thread shutdown: if you don't join the thread, it might be forcefully terminated when the process exists, skipping destructors. Leaving threads unjoined is also bad for reliable unit-testing, and in general bad for overall architecture of the system.

A slight problem with this library is that it turns a thread's panic into Result by forcing you to use the shutdown method. I now think this is a bad idea: it's usually best to escalate the panic instead of catching it, even on the thread boundary. We need to switch "panic, if child thread panicked" behavior.

To do this, we need the following changes:

  • introduce a wrapper around thread::spawn and thread::JoinHandler which joins the thread automatically in Drop, propagating the panic from the child thread if the parent thread is not panicking itself. We should use this wrapper in cases where we spawn bare threads, like here
  • Remove WorkerHandle struct (which exists solely to join the thread) and instead add our JoinHandler (what's a good name here? ScopedThread, ThreadGuard?) to the Worker
  • Change Worker's shutdown method to return a pair of (ScopedThread, Receiver)
  • update usages of thead_worker to the new API, paying close attention to possible deadlocks. Specifically, channel senders should be dropped before ScopedThread, even in case of a panic.
@matklad matklad added good first issue E-medium fun A technically challenging issue with high impact labels Feb 13, 2019
@matklad
Copy link
Member Author

matklad commented Feb 13, 2019

cc @stjepang, this is very related to rust-lang/rust#48830 and shows an interesting interaction between channels and threads (drop sender prior to joining).

@matklad
Copy link
Member Author

matklad commented Feb 13, 2019

Slightly tangential, but, if you are interested in threads and clean cancellation, there's an interesting discussion over here: https://trio.discourse.group/t/structured-concurrency-in-rust/73

@matklad
Copy link
Member Author

matklad commented Feb 13, 2019

drop sender prior to joining

Hm, this seems fun indeed, looks like the pattern we want is

let (sender, receiver) = channel();
let thread = spawn(move || {
    for event in receiver {
        ...
    }
})

// subtle, force sender to be dropped *before* thread, 
// avoiding deadlock if *this* thread panics.
let sender = sender;


// Alternative way to spell this

let thread;
let (sender, receiver) = channel();
thread = spawn(move || {
    for event in receiver {
        ...
    }
})

That's a super uncomfortable level of subtlety, can we do better?

@DJMcNab
Copy link
Contributor

DJMcNab commented Feb 13, 2019

We could just use std::mem::drop manually.

@matklad
Copy link
Member Author

matklad commented Feb 13, 2019

That works for the happy case, but not for the panics, a panic will cause a deadlock

@matklad matklad self-assigned this Feb 14, 2019
matklad added a commit that referenced this issue Feb 14, 2019
matklad added a commit that referenced this issue Feb 14, 2019
matklad added a commit that referenced this issue Feb 14, 2019
bors bot added a commit that referenced this issue Feb 14, 2019
833: automatically wait for worker threads r=matklad a=matklad

closes #817 



Co-authored-by: Aleksey Kladov <[email protected]>
@bors bors bot closed this as completed in #833 Feb 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
E-medium fun A technically challenging issue with high impact
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants