@@ -18,6 +18,7 @@ use io::lazy::Lazy;
1818use io:: { self , BufReader , LineWriter } ;
1919use sync:: { Arc , Mutex , MutexGuard } ;
2020use sys:: stdio;
21+ use sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
2122
2223/// Stdout used by print! and println! macros
2324thread_local ! {
@@ -210,7 +211,7 @@ pub struct Stdout {
210211 // FIXME: this should be LineWriter or BufWriter depending on the state of
211212 // stdout (tty or not). Note that if this is not line buffered it
212213 // should also flush-on-panic or some form of flush-on-abort.
213- inner : Arc < Mutex < LineWriter < StdoutRaw > > > ,
214+ inner : Arc < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > ,
214215}
215216
216217/// A locked reference to the a `Stdout` handle.
@@ -219,7 +220,7 @@ pub struct Stdout {
219220/// method on `Stdout`.
220221#[ stable( feature = "rust1" , since = "1.0.0" ) ]
221222pub struct StdoutLock < ' a > {
222- inner : MutexGuard < ' a , LineWriter < StdoutRaw > > ,
223+ inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
223224}
224225
225226/// Constructs a new reference to the standard output of the current process.
@@ -231,13 +232,13 @@ pub struct StdoutLock<'a> {
231232/// The returned handle implements the `Write` trait.
232233#[ stable( feature = "rust1" , since = "1.0.0" ) ]
233234pub fn stdout ( ) -> Stdout {
234- static INSTANCE : Lazy < Mutex < LineWriter < StdoutRaw > > > = lazy_init ! ( stdout_init) ;
235+ static INSTANCE : Lazy < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > = lazy_init ! ( stdout_init) ;
235236 return Stdout {
236237 inner : INSTANCE . get ( ) . expect ( "cannot access stdout during shutdown" ) ,
237238 } ;
238239
239- fn stdout_init ( ) -> Arc < Mutex < LineWriter < StdoutRaw > > > {
240- Arc :: new ( Mutex :: new ( LineWriter :: new ( stdout_raw ( ) ) ) )
240+ fn stdout_init ( ) -> Arc < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > {
241+ Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( LineWriter :: new ( stdout_raw ( ) ) ) ) )
241242 }
242243}
243244
@@ -264,23 +265,26 @@ impl Write for Stdout {
264265 fn write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
265266 self . lock ( ) . write_all ( buf)
266267 }
267- // Don't override write_fmt as it's possible to run arbitrary code during a
268- // write_fmt, allowing the possibility of a recursive lock (aka deadlock)
268+ fn write_fmt ( & mut self , args : fmt:: Arguments ) -> io:: Result < ( ) > {
269+ self . lock ( ) . write_fmt ( args)
270+ }
269271}
270272#[ stable( feature = "rust1" , since = "1.0.0" ) ]
271273impl < ' a > Write for StdoutLock < ' a > {
272274 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
273- self . inner . write ( & buf[ ..cmp:: min ( buf. len ( ) , OUT_MAX ) ] )
275+ self . inner . borrow_mut ( ) . write ( & buf[ ..cmp:: min ( buf. len ( ) , OUT_MAX ) ] )
276+ }
277+ fn flush ( & mut self ) -> io:: Result < ( ) > {
278+ self . inner . borrow_mut ( ) . flush ( )
274279 }
275- fn flush ( & mut self ) -> io:: Result < ( ) > { self . inner . flush ( ) }
276280}
277281
278282/// A handle to the standard error stream of a process.
279283///
280284/// For more information, see `stderr`
281285#[ stable( feature = "rust1" , since = "1.0.0" ) ]
282286pub struct Stderr {
283- inner : Arc < Mutex < StderrRaw > > ,
287+ inner : Arc < ReentrantMutex < RefCell < StderrRaw > > > ,
284288}
285289
286290/// A locked reference to the a `Stderr` handle.
@@ -289,7 +293,7 @@ pub struct Stderr {
289293/// method on `Stderr`.
290294#[ stable( feature = "rust1" , since = "1.0.0" ) ]
291295pub struct StderrLock < ' a > {
292- inner : MutexGuard < ' a , StderrRaw > ,
296+ inner : ReentrantMutexGuard < ' a , RefCell < StderrRaw > > ,
293297}
294298
295299/// Constructs a new reference to the standard error stream of a process.
@@ -300,13 +304,13 @@ pub struct StderrLock<'a> {
300304/// The returned handle implements the `Write` trait.
301305#[ stable( feature = "rust1" , since = "1.0.0" ) ]
302306pub fn stderr ( ) -> Stderr {
303- static INSTANCE : Lazy < Mutex < StderrRaw > > = lazy_init ! ( stderr_init) ;
307+ static INSTANCE : Lazy < ReentrantMutex < RefCell < StderrRaw > > > = lazy_init ! ( stderr_init) ;
304308 return Stderr {
305309 inner : INSTANCE . get ( ) . expect ( "cannot access stderr during shutdown" ) ,
306310 } ;
307311
308- fn stderr_init ( ) -> Arc < Mutex < StderrRaw > > {
309- Arc :: new ( Mutex :: new ( stderr_raw ( ) ) )
312+ fn stderr_init ( ) -> Arc < ReentrantMutex < RefCell < StderrRaw > > > {
313+ Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( stderr_raw ( ) ) ) )
310314 }
311315}
312316
@@ -333,14 +337,18 @@ impl Write for Stderr {
333337 fn write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
334338 self . lock ( ) . write_all ( buf)
335339 }
336- // Don't override write_fmt for the same reasons as Stdout
340+ fn write_fmt ( & mut self , args : fmt:: Arguments ) -> io:: Result < ( ) > {
341+ self . lock ( ) . write_fmt ( args)
342+ }
337343}
338344#[ stable( feature = "rust1" , since = "1.0.0" ) ]
339345impl < ' a > Write for StderrLock < ' a > {
340346 fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
341- self . inner . write ( & buf[ ..cmp:: min ( buf. len ( ) , OUT_MAX ) ] )
347+ self . inner . borrow_mut ( ) . write ( & buf[ ..cmp:: min ( buf. len ( ) , OUT_MAX ) ] )
348+ }
349+ fn flush ( & mut self ) -> io:: Result < ( ) > {
350+ self . inner . borrow_mut ( ) . flush ( )
342351 }
343- fn flush ( & mut self ) -> io:: Result < ( ) > { self . inner . flush ( ) }
344352}
345353
346354/// Resets the task-local stderr handle to the specified writer
0 commit comments