-
Notifications
You must be signed in to change notification settings - Fork 13.9k
Description
io::{Stdout, Stderr, StdoutLock, StderrLock} are not UnwindSafe:
use std::io::{Stdout, Stderr, StdoutLock, StderrLock};
use std::panic::UnwindSafe;
fn assert_unwind_safe<T: UnwindSafe>() {}
fn main() {
assert_unwind_safe::<Stdout>();
assert_unwind_safe::<Stderr>();
assert_unwind_safe::<StdoutLock<'static>>();
assert_unwind_safe::<StderrLock<'static>>();
}However, because they are protected by mutexes, it doesn't make sense why these handles shouldn't be UnwindSafe. It seems to be an oversight because they use ReentrantMutex internally, which transitively opts-out of UnwindSafe because it contains an UnsafeCell.
This makes io::Stdout a pain to use with slog which requires Send + Sync + UnwindSafe on its output, necessitating a second mutex wrapping the handle or a custom wrapper implementing UnwindSafe. AssertUnwindSafe is not a solution here because it doesn't implement Write for its contained type.
Either ReentrantMutex should manually implement UnwindSafe as well, or the stdio handles should. I also recommend adding delegated impls of Read, Write and BufRead to AssertUnwindSafe.
Addendum: I'm still having problems with slog but for another reason; slog_json::Json is also not UnwindSafe or Sync because it uses RefCell internally.
Addendum 2: because it uses Mutex and not ReentrantMutex, Stdin is already UnwindSafe + RefUnwindSafe, and thus StdinLock is too. My original code example didn't error for those types but I didn't notice.