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.