Skip to content
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

tokio::run doesn't propogate panics from futures #495

Closed
canndrew opened this issue Jul 20, 2018 · 19 comments
Closed

tokio::run doesn't propogate panics from futures #495

canndrew opened this issue Jul 20, 2018 · 19 comments

Comments

@canndrew
Copy link
Contributor

I assumed the following test would fail, but it currently passes.

#[test]
fn my_test() {
    tokio::run(future::lazy(|| -> Result<_, _> {
        panic!("oh no!")
    }))
}

Is this expected behaviour? It doesn't seem like it should be.

@aep
Copy link
Contributor

aep commented Jul 22, 2018

got the same issue. setting panic hook to exit in every test is my workaround: https://doc.rust-lang.org/std/panic/fn.set_hook.html

@carllerche
Copy link
Member

@canndrew this is the intent. tokio::run starts the system. It would be as if a panic on a thread caused all threads to crash.

You might be wanting block_on, which (should) propagate panics.

Closing for now. Let me know if this is incorrect and I can open again.

@canndrew
Copy link
Contributor Author

Sorry, you're right, I misunderstood what tokio::run was for. However it might be nice if there was a tokio::block_on convenience function, rather than having to start a runtime manually (this would be especially useful for tests).

@leoyvens
Copy link

leoyvens commented Aug 7, 2018

It would be as if a panic on a thread caused all threads to crash.

@carllerche That's exactly what I want for tests. A configuration for the Runtime to propagate any panic would be nice.

@carllerche
Copy link
Member

@leodasvacas does block_on not satisfy your case?

@leoyvens
Copy link

leoyvens commented Aug 7, 2018

@carllerche No because it does not compose. If I block_on(future) then future might spawn a new task where a panic would not fail the test.

@jeff-hiner
Copy link

I hate to drag back open an old issue, but this is still a problem. I can't find a way to reliably capture threadpool panics in tests. I have a codebase liberally using tokio::spawn that I'm in the middle of fuzzing, and certain inputs cause those spawned futures to error or panic. From the standpoint of tokio::spawn there appears to be no behavioral difference between a passed Future returning an err or an ok. I guess this is like being unable to react to panics in a detached thread? What's the joinable thread alternative, and is it documented somewhere I'm not seeing?

@carllerche
Copy link
Member

I'd be fine having a config option passed to runtime::Builder that allows configuring the behavior.

@canndrew
Copy link
Contributor Author

How about making it so tokio propagates panics in debug mode but not release mode?

@carllerche
Copy link
Member

We can probably start w/ a builder option, then decide after that what the defaults should be?

@jeff-hiner
Copy link

Yeah, differing behavior in debug and release modes I think is asking for trouble.

@ry
Copy link
Contributor

ry commented Apr 14, 2019

Panics should crash the program. This feature continues to introduce bugs in Deno. (Most recently denoland/deno#2098)

ry added a commit to ry/deno that referenced this issue Apr 14, 2019
ry added a commit to ry/deno that referenced this issue Apr 14, 2019
This is to work around Tokio's panic recovery feautre.
Ref tokio-rs/tokio#495
Ref tokio-rs/tokio#209
Ref denoland#1311
Fixes denoland#2097
ry added a commit to ry/deno that referenced this issue Apr 14, 2019
This is to work around Tokio's panic recovery feature.
Ref tokio-rs/tokio#495
Ref tokio-rs/tokio#209
Ref denoland#1311
Fixes denoland#2097
ry added a commit to ry/deno that referenced this issue Apr 14, 2019
This is to work around Tokio's panic recovery feature.
Ref tokio-rs/tokio#495
Ref tokio-rs/tokio#209
Ref denoland#1311
Fixes denoland#2097
ry added a commit to denoland/deno that referenced this issue Apr 14, 2019
This is to work around Tokio's panic recovery feature.
Ref tokio-rs/tokio#495
Ref tokio-rs/tokio#209
Ref #1311
Fixes #2097
@carllerche
Copy link
Member

I will re-open since the action item is to add a config option.

I believe the story will be better in 0.2.

@carllerche carllerche reopened this Apr 17, 2019
@leoyvens
Copy link

leoyvens commented Apr 17, 2019

I'd also like to be able to override the global panic behaviour per-task, so that selected tasks (and child tasks) still catch panics.

@ry
Copy link
Contributor

ry commented Apr 17, 2019

Shouldn’t it be the responsibility of user code to catch their panics? I can imagine a web server wanting to serve special html 500 error code pages. At tokio’s layer of abstraction, catching panics isn’t helpful because it doesn’t know how to properly service them.

@jeff-hiner
Copy link

I think what I was getting at was more that tokio::run is passed something which may error (or panic, because any code in Rust can legally panic) but it does not have a return type at all. That's a design decision. This inherently delegates error handling to the runtime which, as you've said, is not equipped to deal with these problems.

I would expect the ergonomics to be set up so that the runtime returns a Result<(), ...> in a way that makes errors from tokio::spawn tasks available. I expect tokio to offer behavior consistent with std::thread::JoinHandle::join. I can spawn a thread and join it, in which case I'll get a Result wrapping any panics. Or I can spawn a thread and drop its JoinHandle, in which case panics will be silently dropped. There are cases for using both within a single program.

For your webserver example, the main server should propagate any errors upstream terminating the runner, and the client tasks should probably just discard any errors. If you drop every thread panic on the floor, you can wind up with scenarios where your main server thread panics, other spawned tasks run forever, and your program just keeps chugging along unable to service requests. If you insist that every thread panic terminates the runner, then panics in client threads will terminate your server. This is safer, but less ergonomic.

Right now there's no way to tell the runner which threads should be treated as detached and which ones should terminate the runtime. I can see an implementation with tokio::spawn and tokio::spawn_detached calls, where panics in the former terminate the runner and panics in the latter are silently discarded.

@carllerche
Copy link
Member

I don't think this issue is relevant anymore:

  • Runtimes will allow configuring how panics are handled (by default, they will swallow, which is OK because...)
  • spawn! will return a handle annotated with must_use. panics are propagaged via this (Provide spawn macro #1180).
  • tokio::run is removed in favor of an attribute macro.

@carllerche
Copy link
Member

If I am wrong, please post here and I can update the appropriate issue.

Tzikas added a commit to Tzikas/squares that referenced this issue Sep 10, 2019
This is to work around Tokio's panic recovery feature.
Ref tokio-rs/tokio#495
Ref tokio-rs/tokio#209
Ref denoland/deno#1311
Fixes #2097
@mimoo
Copy link

mimoo commented Sep 16, 2019

@jeff-at-dwelo don't you have issues fuzzing concurrent code anyway? As it might throw the fuzzer off?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants