@@ -18,6 +18,7 @@ use io::lazy::Lazy;
18
18
use io:: { self , BufReader , LineWriter } ;
19
19
use sync:: { Arc , Mutex , MutexGuard } ;
20
20
use sys:: stdio;
21
+ use sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
21
22
22
23
/// Stdout used by print! and println! macros
23
24
thread_local ! {
@@ -210,7 +211,7 @@ pub struct Stdout {
210
211
// FIXME: this should be LineWriter or BufWriter depending on the state of
211
212
// stdout (tty or not). Note that if this is not line buffered it
212
213
// 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 > > > > ,
214
215
}
215
216
216
217
/// A locked reference to the a `Stdout` handle.
@@ -219,7 +220,7 @@ pub struct Stdout {
219
220
/// method on `Stdout`.
220
221
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
221
222
pub struct StdoutLock < ' a > {
222
- inner : MutexGuard < ' a , LineWriter < StdoutRaw > > ,
223
+ inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
223
224
}
224
225
225
226
/// Constructs a new reference to the standard output of the current process.
@@ -231,13 +232,13 @@ pub struct StdoutLock<'a> {
231
232
/// The returned handle implements the `Write` trait.
232
233
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
233
234
pub 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) ;
235
236
return Stdout {
236
237
inner : INSTANCE . get ( ) . expect ( "cannot access stdout during shutdown" ) ,
237
238
} ;
238
239
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 ( ) ) ) ) )
241
242
}
242
243
}
243
244
@@ -264,23 +265,26 @@ impl Write for Stdout {
264
265
fn write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
265
266
self . lock ( ) . write_all ( buf)
266
267
}
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
+ }
269
271
}
270
272
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
271
273
impl < ' a > Write for StdoutLock < ' a > {
272
274
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 ( )
274
279
}
275
- fn flush ( & mut self ) -> io:: Result < ( ) > { self . inner . flush ( ) }
276
280
}
277
281
278
282
/// A handle to the standard error stream of a process.
279
283
///
280
284
/// For more information, see `stderr`
281
285
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
282
286
pub struct Stderr {
283
- inner : Arc < Mutex < StderrRaw > > ,
287
+ inner : Arc < ReentrantMutex < RefCell < StderrRaw > > > ,
284
288
}
285
289
286
290
/// A locked reference to the a `Stderr` handle.
@@ -289,7 +293,7 @@ pub struct Stderr {
289
293
/// method on `Stderr`.
290
294
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
291
295
pub struct StderrLock < ' a > {
292
- inner : MutexGuard < ' a , StderrRaw > ,
296
+ inner : ReentrantMutexGuard < ' a , RefCell < StderrRaw > > ,
293
297
}
294
298
295
299
/// Constructs a new reference to the standard error stream of a process.
@@ -300,13 +304,13 @@ pub struct StderrLock<'a> {
300
304
/// The returned handle implements the `Write` trait.
301
305
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
302
306
pub fn stderr ( ) -> Stderr {
303
- static INSTANCE : Lazy < Mutex < StderrRaw > > = lazy_init ! ( stderr_init) ;
307
+ static INSTANCE : Lazy < ReentrantMutex < RefCell < StderrRaw > > > = lazy_init ! ( stderr_init) ;
304
308
return Stderr {
305
309
inner : INSTANCE . get ( ) . expect ( "cannot access stderr during shutdown" ) ,
306
310
} ;
307
311
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 ( ) ) ) )
310
314
}
311
315
}
312
316
@@ -333,14 +337,18 @@ impl Write for Stderr {
333
337
fn write_all ( & mut self , buf : & [ u8 ] ) -> io:: Result < ( ) > {
334
338
self . lock ( ) . write_all ( buf)
335
339
}
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
+ }
337
343
}
338
344
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
339
345
impl < ' a > Write for StderrLock < ' a > {
340
346
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 ( )
342
351
}
343
- fn flush ( & mut self ) -> io:: Result < ( ) > { self . inner . flush ( ) }
344
352
}
345
353
346
354
/// Resets the task-local stderr handle to the specified writer
0 commit comments