diff options
| author | Fenrir <[email protected]> | 2018-08-19 17:48:00 -0600 |
|---|---|---|
| committer | Fenrir <[email protected]> | 2018-08-19 17:56:18 -0600 |
| commit | 5d28bfcfd6086c3328837de9695099ea39048d0d (patch) | |
| tree | a514fde042ff2a504a03305bfe0894ff8cd8d47e /ctr-std/src/io/stdio.rs | |
| parent | Update for latest nightly 2018-06-09 (#70) (diff) | |
| download | ctru-rs-5d28bfcfd6086c3328837de9695099ea39048d0d.tar.xz ctru-rs-5d28bfcfd6086c3328837de9695099ea39048d0d.zip | |
Update for nightly-2018-08-18
Diffstat (limited to 'ctr-std/src/io/stdio.rs')
| -rw-r--r-- | ctr-std/src/io/stdio.rs | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/ctr-std/src/io/stdio.rs b/ctr-std/src/io/stdio.rs index 2472bed..1f256f5 100644 --- a/ctr-std/src/io/stdio.rs +++ b/ctr-std/src/io/stdio.rs @@ -21,7 +21,7 @@ use thread::LocalKey; /// Stdout used by print! and println! macros thread_local! { - static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = { + static LOCAL_STDOUT: RefCell<Option<Box<dyn Write + Send>>> = { RefCell::new(None) } } @@ -197,12 +197,13 @@ pub struct StdinLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { - static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(stdin_init); + static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = unsafe { Lazy::new(stdin_init) }; return Stdin { inner: INSTANCE.get().expect("cannot access stdin during shutdown"), }; fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> { + // This must not reentrantly access `INSTANCE` let stdin = match stdin_raw() { Ok(stdin) => Maybe::Real(stdin), _ => Maybe::Fake @@ -396,12 +397,13 @@ pub struct StdoutLock<'a> { #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> - = Lazy::new(stdout_init); + = unsafe { Lazy::new(stdout_init) }; return Stdout { inner: INSTANCE.get().expect("cannot access stdout during shutdown"), }; fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> { + // This must not reentrantly access `INSTANCE` let stdout = match stdout_raw() { Ok(stdout) => Maybe::Real(stdout), _ => Maybe::Fake, @@ -531,12 +533,14 @@ pub struct StderrLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { - static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(stderr_init); + static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = + unsafe { Lazy::new(stderr_init) }; return Stderr { inner: INSTANCE.get().expect("cannot access stderr during shutdown"), }; fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> { + // This must not reentrantly access `INSTANCE` let stderr = match stderr_raw() { Ok(stderr) => Maybe::Real(stderr), _ => Maybe::Fake, @@ -624,7 +628,7 @@ impl<'a> fmt::Debug for StderrLock<'a> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { +pub fn set_panic(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> { use panicking::LOCAL_STDERR; use mem; LOCAL_STDERR.with(move |slot| { @@ -648,7 +652,7 @@ pub fn set_panic(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { with a more general mechanism", issue = "0")] #[doc(hidden)] -pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { +pub fn set_print(sink: Option<Box<dyn Write + Send>>) -> Option<Box<dyn Write + Send>> { use mem; LOCAL_STDOUT.with(move |slot| { mem::replace(&mut *slot.borrow_mut(), sink) @@ -670,7 +674,7 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> { /// However, if the actual I/O causes an error, this function does panic. fn print_to<T>( args: fmt::Arguments, - local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>, + local_s: &'static LocalKey<RefCell<Option<Box<dyn Write+Send>>>>, global_s: fn() -> T, label: &str, ) @@ -712,10 +716,32 @@ pub fn _eprint(args: fmt::Arguments) { #[cfg(test)] mod tests { + use panic::{UnwindSafe, RefUnwindSafe}; use thread; use super::*; #[test] + fn stdout_unwind_safe() { + assert_unwind_safe::<Stdout>(); + } + #[test] + fn stdoutlock_unwind_safe() { + assert_unwind_safe::<StdoutLock>(); + assert_unwind_safe::<StdoutLock<'static>>(); + } + #[test] + fn stderr_unwind_safe() { + assert_unwind_safe::<Stderr>(); + } + #[test] + fn stderrlock_unwind_safe() { + assert_unwind_safe::<StderrLock>(); + assert_unwind_safe::<StderrLock<'static>>(); + } + + fn assert_unwind_safe<T: UnwindSafe + RefUnwindSafe>() {} + + #[test] #[cfg_attr(target_os = "emscripten", ignore)] fn panic_doesnt_poison() { thread::spawn(|| { |