Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upAdd thread-local custom panic handlers to customize the behavior of thread panics #1100
Conversation
yberreby
added some commits
May 1, 2015
This comment has been minimized.
This comment has been minimized.
|
Related: #1089
It should be noted, that state of (silent) panic is not entirely undetectable: join on thread returns Err side of Result and main thread exits the process with a certain error code. |
yberreby
changed the title
make `panic!()` silent when called without arguments
make `panic!()` output nothing when called without arguments
May 1, 2015
This comment has been minimized.
This comment has been minimized.
|
This sounds great to me. |
This comment has been minimized.
This comment has been minimized.
abonander
commented
May 1, 2015
|
This doesn't need to be implemented as another rule to In the |
This comment has been minimized.
This comment has been minimized.
bluss
commented
May 1, 2015
|
Why change the behavior of plain Panics can carry arbitrary values so in libstd style I guess we could have a I'm not sure how feasible this is to implement, but as you know the panic value is wrapped in Edit: You can totally add the check for a panic options here in the code and silence the panic message. |
This comment has been minimized.
This comment has been minimized.
|
FWIW, I don't think making this change should be considered a violation of stability. It wouldn't affect the API, so there's no backwards-compatibility issues as far as compilation goes, and I'm finding it hard to imagine how turning off a message printed to stderr on task panic would break anybody. That said, I'd still prefer to have to opt-in to silent panics. The idea of passing a panic configuration value to |
This comment has been minimized.
This comment has been minimized.
abonander
commented
May 2, 2015
|
@kballard It breaks the invariant that |
This comment has been minimized.
This comment has been minimized.
|
@cybergeek94 Printing a message to stderr is not part of the documentation for |
This comment has been minimized.
This comment has been minimized.
|
So having |
This comment has been minimized.
This comment has been minimized.
|
One more thing: even though we consciously and infamously support "catching" unwinding, that doesn't mean we should be encouraging that use as a normal error-handling solution. A panic at runtime indicates a problem, and if you're really panicking so often that you're clogging up your logfiles then I need to ask what your architecture is like that you feel the need to resort to that approach. |
This comment has been minimized.
This comment has been minimized.
bluss
commented
May 2, 2015
|
@kballard Panicking with a known value for panic_silent! is of course a reasonable idea. I wanted to point out that panicking with values is already exposed, you can pass an arbitrary value to |
This comment has been minimized.
This comment has been minimized.
|
Instead of having panic_silent!(), might it make sense to have panic!(panic::silent) or something? Basically add a value that isn't currently accepted to panic!(). |
This comment has been minimized.
This comment has been minimized.
|
Could changing the output of plain FWIW, I think This way we don't lose debugging information on panics, and we can have tight code in release builds. |
This comment has been minimized.
This comment has been minimized.
|
I think there is a related problem which makes panic not very useful for messaging failure and that there is nothing it can carry. It's very hard for a panic handler to figure out why exactly something panicked. You can't even set an integer to signal something upwards. I think there is more that needs doing than just removing an error message. |
This comment has been minimized.
This comment has been minimized.
@bluss is right, the logging lies in From what has been brought up, I think the best solution is as follow:
Here's how it would be used: use std::thread;
fn main() {
thread::spawn(|| {
// use the default panic handler, `debug`, the one we currently have
some_optional.unwrap();
}).join();
thread::spawn(|| {
// Always use the `silent` handler
thread::on_panic(thread::handlers::silent);
// This will never display a message
// Use cases:
// - abort thread silently on errors unrecoverable at its level,
// but recoverable at the process level, and spawn a new one
a_third_party_function_that_could_fail();
}).join();
thread::spawn(|| {
// Always use the `basic` handler
thread::on_panic(thread::handlers::basic);
// This will simply display whatever is passed to `panic!` on panic,
// much like println!()
// Use cases:
// - abort thread on invalid input with a user-friendly message
if !is_valid(input) {
panic!("Invalid input - please try again");
} else {
// ...
}
}).join();
}This would undoubtedly offer the most flexibility, without breaking backward compatibility. Additionally, To have debug messages on debug builds and bare-bones messages on release builds, users could simply do this: thread::on_panic(
if cfg!(debug) {
thread::handlers::debug
} else {
thread::handlers::basic
}
);Or this could be the default, but I'm not sure rustc supports debug flags, or whether this would be desirable. What do you think? PS: I'm not familiar with the RFC process - should I update the RFC to integrate these changes, even if it implies changing the feature name from |
This comment has been minimized.
This comment has been minimized.
Or carry none.
Changing that to
You already can replace panic handler to your own by not using libstd and providing your own
Its your RFC, you may change it anytime until it is accepted. Just note what changes you made and keep commit history. From both implementation complexity and API standpoint I, personally, prefer original suggestion. |
This comment has been minimized.
This comment has been minimized.
This is arguably not handy for something as simple as changing what is output to
Glad to know that! I'm working on the second iteration.
It surely is simpler, but it's less customizable and flexible. I believe |
yberreby
changed the title
make `panic!()` output nothing when called without arguments
allow customization of the output of `panic!()` to stderr with 'panic handlers'
May 2, 2015
This comment has been minimized.
This comment has been minimized.
|
I've heavily modified the RFC in the last commit. |
This comment has been minimized.
This comment has been minimized.
|
+1 |
This comment has been minimized.
This comment has been minimized.
|
+1, although there are a few things that need clarifying:
|
This comment has been minimized.
This comment has been minimized.
|
-1. What bstrie said on encouraging use of panic. Catching panics should only be done for esoteric FFI reasons. |
This comment has been minimized.
This comment has been minimized.
|
@Ericson2314 And yet we are currently allowing panic catching. The standard library accounts for panics (mutex poisoning comes to my mind). A lot of library functions can and do panic. If we are to drop support for clean panicking, we should drop support for We need to be consistent. Either we support panics, or we don't. If we do, we need to do it right. Unwinding a thread's stack and running destructors has uses, even though I would often prefer a @Diggsey I doubt I'm qualified enough, but your questions alone shed light on potential problems, so it would probably better to leave refactoring of the handler mechanism (which already exists, although it's unstable) for a later RFC, and change this one to a simple logging mode selection, which changes the behavior of the I'll update the RFC, thanks for your comments. |
This comment has been minimized.
This comment has been minimized.
|
An alternative to a |
This comment has been minimized.
This comment has been minimized.
|
@sfackler yeah as @Diggsey mentioned we run these handlers currently before unwinding, so the double-panic part may come into play. I'm somewhat leaning more towards only having a global handler as it allows building thread-local handlers on top, so in that sense it seems more flexible. Along those lies I'd want the handler to be |
This comment has been minimized.
This comment has been minimized.
|
+1 for this. Writing an ugly message to stderr isn't the best thing to do when you have a bug. |
This comment has been minimized.
This comment has been minimized.
dpc
commented
Sep 18, 2015
|
+1 My current problem is that I am working on a library using coroutines, that is supposed to handle panics of coroutines it manages. It also implements tests that exercises panic conditions in multithreading cases (so the terminal gets severely trashed). |
This comment has been minimized.
This comment has been minimized.
|
@dpc Of course as we know from certain logging frameworks the right thing to do in such cases is to use an MPSC queue + thread to write the messages. |
This comment has been minimized.
This comment has been minimized.
dpc
commented
Sep 18, 2015
|
@llogiq : I don't understand. |
This comment has been minimized.
This comment has been minimized.
|
Your problem is that multiple threads may write to the console. To avoid trashing the terminal with concurrent writes, you need to synchronize the output. Now there are two ways to do that: Either have the panic output lock the console (which has its own set of problems), or send the stack info to a helper thread that your library spins up to output the stack traces. The panic helper thread then becomes the synchronization point. Of course to send the stack infos, one needs some kind of MPSC queue (e.g. a channel). |
This comment has been minimized.
This comment has been minimized.
dpc
commented
Sep 18, 2015
|
I don't want to synchronize anything. I'm not printing anything. It's just |
This comment has been minimized.
This comment has been minimized.
|
So you want to silence |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
dpc
commented
Sep 18, 2015
|
Yes. I just wanted to state my usecase, and why I +1 this RFC. |
This comment has been minimized.
This comment has been minimized.
|
|
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
When logging to stderr you can rely on |
jonas-schievink
referenced this pull request
Sep 30, 2015
Closed
Toggle stack unwinding without printing error message #28752
This comment has been minimized.
This comment has been minimized.
|
What's the status of this? |
This comment has been minimized.
This comment has been minimized.
|
@arielb1 As per #1100 (comment), there are some problems with my last proposal. The idea itself - custom panic handler - seems to have been well received, but the proposed implementation is far from perfect. Unfortunately, my studies take up a lot of time so I probably won't be able to come up with a new, reasonably good implementation spec in the following months. So unless somebody else does, well, it may take a long time for this to be accepted and implemented. |
This comment has been minimized.
This comment has been minimized.
|
cc @ranma42 (I started doing some work on TLS and panicking, I might be able to contribute if I get some spare time) |
This comment has been minimized.
This comment has been minimized.
Syntaf
commented
Oct 17, 2015
|
I'm all for this PR. I help develop a terminal graphics library and stderr is not a valid stream we want to be printing exceptions to. We currently have no tools to copy / redirect stderr in rust, this would allow us to properly do so |
Syntaf
referenced this pull request
Oct 17, 2015
Merged
Display exceptions via gag and stderr redirection #22
This comment has been minimized.
This comment has been minimized.
This RFC still wouldn’t allow copying or redirecting stderr per se. It is, however, already possible on at least POSIX systems by using use std::os::raw::c_int;
extern { fn dup2(fd1: c_int, fd2: c_int) };
fn main(){
// create a fd
unsafe { assert!(dup2(your_fd, 2) != -1); }
} |
This comment has been minimized.
This comment has been minimized.
|
For those interested, @sfackler has posted an alternate RFC to this one which is more centered around global handlers. |
This comment has been minimized.
This comment has been minimized.
|
Note that this entering FCP at the same time as #1328 and the two will likely be decided upon as a unit. |
alexcrichton
added
the
final-comment-period
label
Nov 19, 2015
This comment has been minimized.
This comment has been minimized.
|
@alexcrichton I'm pretty sure this RFC can't be merged as-is, and I wouldn't want it to, since the issues @sfackler's pointed out haven't been addressed. Should I close it now? |
This comment has been minimized.
This comment has been minimized.
|
It's true that the libs team would be unlikely to merge this as-is, but it represents an alternative strategy from #1328 that we're willing to consider. Along those lines we're fine leaving this open as a proxy for the "thread local strategy" vs the "global handler strategy". |
This comment has been minimized.
This comment has been minimized.
|
The libs team discussed this RFC during triage yesterday and the conclusion was to merge #1328 and close this one. Thanks again for the RFC though @yberreby! |
yberreby commentedMay 1, 2015
Rendered
EDIT: heavily modified since the first commits!
EDIT 2 (3rd of July): provided implementation details and PoC (see #1100 (comment))