@@ -19,6 +19,7 @@ use io::{self, BufReader, LineWriter};
19
19
use sync:: { Arc , Mutex , MutexGuard } ;
20
20
use sys:: stdio;
21
21
use sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
22
+ use libc;
22
23
23
24
/// Stdout used by print! and println! macros
24
25
thread_local ! {
@@ -52,7 +53,7 @@ struct StderrRaw(stdio::Stderr);
52
53
/// handles is **not** available to raw handles returned from this function.
53
54
///
54
55
/// The returned handle has no external synchronization or buffering.
55
- fn stdin_raw ( ) -> StdinRaw { StdinRaw ( stdio:: Stdin :: new ( ) ) }
56
+ fn stdin_raw ( ) -> io :: Result < StdinRaw > { stdio:: Stdin :: new ( ) . map ( StdinRaw ) }
56
57
57
58
/// Constructs a new raw handle to the standard input stream of this process.
58
59
///
@@ -63,7 +64,7 @@ fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
63
64
///
64
65
/// The returned handle has no external synchronization or buffering layered on
65
66
/// top.
66
- fn stdout_raw ( ) -> StdoutRaw { StdoutRaw ( stdio:: Stdout :: new ( ) ) }
67
+ fn stdout_raw ( ) -> io :: Result < StdoutRaw > { stdio:: Stdout :: new ( ) . map ( StdoutRaw ) }
67
68
68
69
/// Constructs a new raw handle to the standard input stream of this process.
69
70
///
@@ -72,7 +73,7 @@ fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
72
73
///
73
74
/// The returned handle has no external synchronization or buffering layered on
74
75
/// top.
75
- fn stderr_raw ( ) -> StderrRaw { StderrRaw ( stdio:: Stderr :: new ( ) ) }
76
+ fn stderr_raw ( ) -> io :: Result < StderrRaw > { stdio:: Stderr :: new ( ) . map ( StderrRaw ) }
76
77
77
78
impl Read for StdinRaw {
78
79
fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > { self . 0 . read ( buf) }
@@ -86,6 +87,48 @@ impl Write for StderrRaw {
86
87
fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
87
88
}
88
89
90
+ enum Maybe < T > {
91
+ Real ( T ) ,
92
+ Fake ,
93
+ }
94
+
95
+ impl < W : io:: Write > io:: Write for Maybe < W > {
96
+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
97
+ match * self {
98
+ Maybe :: Real ( ref mut w) => handle_ebadf ( w. write ( buf) , buf. len ( ) ) ,
99
+ Maybe :: Fake => Ok ( buf. len ( ) )
100
+ }
101
+ }
102
+
103
+ fn flush ( & mut self ) -> io:: Result < ( ) > {
104
+ match * self {
105
+ Maybe :: Real ( ref mut w) => handle_ebadf ( w. flush ( ) , ( ) ) ,
106
+ Maybe :: Fake => Ok ( ( ) )
107
+ }
108
+ }
109
+ }
110
+
111
+ impl < R : io:: Read > io:: Read for Maybe < R > {
112
+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
113
+ match * self {
114
+ Maybe :: Real ( ref mut r) => handle_ebadf ( r. read ( buf) , buf. len ( ) ) ,
115
+ Maybe :: Fake => Ok ( 0 )
116
+ }
117
+ }
118
+ }
119
+
120
+ fn handle_ebadf < T > ( r : io:: Result < T > , default : T ) -> io:: Result < T > {
121
+ #[ cfg( windows) ]
122
+ const ERR : libc:: c_int = libc:: ERROR_INVALID_HANDLE ;
123
+ #[ cfg( not( windows) ) ]
124
+ const ERR : libc:: c_int = libc:: EBADF ;
125
+
126
+ match r {
127
+ Err ( ref e) if e. raw_os_error ( ) == Some ( ERR ) => Ok ( default) ,
128
+ r => r
129
+ }
130
+ }
131
+
89
132
/// A handle to the standard input stream of a process.
90
133
///
91
134
/// Each handle is a shared reference to a global buffer of input data to this
@@ -99,7 +142,7 @@ impl Write for StderrRaw {
99
142
/// Created by the function `io::stdin()`.
100
143
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
101
144
pub struct Stdin {
102
- inner : Arc < Mutex < BufReader < StdinRaw > > > ,
145
+ inner : Arc < Mutex < BufReader < Maybe < StdinRaw > > > > ,
103
146
}
104
147
105
148
/// A locked reference to the a `Stdin` handle.
@@ -108,7 +151,7 @@ pub struct Stdin {
108
151
/// constructed via the `lock` method on `Stdin`.
109
152
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
110
153
pub struct StdinLock < ' a > {
111
- inner : MutexGuard < ' a , BufReader < StdinRaw > > ,
154
+ inner : MutexGuard < ' a , BufReader < Maybe < StdinRaw > > > ,
112
155
}
113
156
114
157
/// Creates a new handle to the global standard input stream of this process.
@@ -122,20 +165,25 @@ pub struct StdinLock<'a> {
122
165
/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
123
166
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
124
167
pub fn stdin ( ) -> Stdin {
125
- static INSTANCE : Lazy < Mutex < BufReader < StdinRaw > > > = Lazy :: new ( stdin_init) ;
168
+ static INSTANCE : Lazy < Mutex < BufReader < Maybe < StdinRaw > > > > = Lazy :: new ( stdin_init) ;
126
169
return Stdin {
127
170
inner : INSTANCE . get ( ) . expect ( "cannot access stdin during shutdown" ) ,
128
171
} ;
129
172
130
- fn stdin_init ( ) -> Arc < Mutex < BufReader < StdinRaw > > > {
173
+ fn stdin_init ( ) -> Arc < Mutex < BufReader < Maybe < StdinRaw > > > > {
174
+ let stdin = match stdin_raw ( ) {
175
+ Ok ( stdin) => Maybe :: Real ( stdin) ,
176
+ _ => Maybe :: Fake
177
+ } ;
178
+
131
179
// The default buffer capacity is 64k, but apparently windows
132
180
// doesn't like 64k reads on stdin. See #13304 for details, but the
133
181
// idea is that on windows we use a slightly smaller buffer that's
134
182
// been seen to be acceptable.
135
183
Arc :: new ( Mutex :: new ( if cfg ! ( windows) {
136
- BufReader :: with_capacity ( 8 * 1024 , stdin_raw ( ) )
184
+ BufReader :: with_capacity ( 8 * 1024 , stdin )
137
185
} else {
138
- BufReader :: new ( stdin_raw ( ) )
186
+ BufReader :: new ( stdin )
139
187
} ) )
140
188
}
141
189
}
@@ -181,6 +229,7 @@ impl<'a> Read for StdinLock<'a> {
181
229
self . inner . read ( buf)
182
230
}
183
231
}
232
+
184
233
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
185
234
impl < ' a > BufRead for StdinLock < ' a > {
186
235
fn fill_buf ( & mut self ) -> io:: Result < & [ u8 ] > { self . inner . fill_buf ( ) }
@@ -215,7 +264,7 @@ pub struct Stdout {
215
264
// FIXME: this should be LineWriter or BufWriter depending on the state of
216
265
// stdout (tty or not). Note that if this is not line buffered it
217
266
// should also flush-on-panic or some form of flush-on-abort.
218
- inner : Arc < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > ,
267
+ inner : Arc < ReentrantMutex < RefCell < LineWriter < Maybe < StdoutRaw > > > > > ,
219
268
}
220
269
221
270
/// A locked reference to the a `Stdout` handle.
@@ -224,7 +273,7 @@ pub struct Stdout {
224
273
/// method on `Stdout`.
225
274
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
226
275
pub struct StdoutLock < ' a > {
227
- inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
276
+ inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < Maybe < StdoutRaw > > > > ,
228
277
}
229
278
230
279
/// Constructs a new reference to the standard output of the current process.
@@ -236,13 +285,18 @@ pub struct StdoutLock<'a> {
236
285
/// The returned handle implements the `Write` trait.
237
286
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
238
287
pub fn stdout ( ) -> Stdout {
239
- static INSTANCE : Lazy < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > = Lazy :: new ( stdout_init) ;
288
+ static INSTANCE : Lazy < ReentrantMutex < RefCell < LineWriter < Maybe < StdoutRaw > > > > >
289
+ = Lazy :: new ( stdout_init) ;
240
290
return Stdout {
241
291
inner : INSTANCE . get ( ) . expect ( "cannot access stdout during shutdown" ) ,
242
292
} ;
243
293
244
- fn stdout_init ( ) -> Arc < ReentrantMutex < RefCell < LineWriter < StdoutRaw > > > > {
245
- Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( LineWriter :: new ( stdout_raw ( ) ) ) ) )
294
+ fn stdout_init ( ) -> Arc < ReentrantMutex < RefCell < LineWriter < Maybe < StdoutRaw > > > > > {
295
+ let stdout = match stdout_raw ( ) {
296
+ Ok ( stdout) => Maybe :: Real ( stdout) ,
297
+ _ => Maybe :: Fake ,
298
+ } ;
299
+ Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( LineWriter :: new ( stdout) ) ) )
246
300
}
247
301
}
248
302
@@ -288,7 +342,7 @@ impl<'a> Write for StdoutLock<'a> {
288
342
/// For more information, see `stderr`
289
343
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
290
344
pub struct Stderr {
291
- inner : Arc < ReentrantMutex < RefCell < StderrRaw > > > ,
345
+ inner : Arc < ReentrantMutex < RefCell < Maybe < StderrRaw > > > > ,
292
346
}
293
347
294
348
/// A locked reference to the a `Stderr` handle.
@@ -297,7 +351,7 @@ pub struct Stderr {
297
351
/// method on `Stderr`.
298
352
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
299
353
pub struct StderrLock < ' a > {
300
- inner : ReentrantMutexGuard < ' a , RefCell < StderrRaw > > ,
354
+ inner : ReentrantMutexGuard < ' a , RefCell < Maybe < StderrRaw > > > ,
301
355
}
302
356
303
357
/// Constructs a new reference to the standard error stream of a process.
@@ -308,13 +362,17 @@ pub struct StderrLock<'a> {
308
362
/// The returned handle implements the `Write` trait.
309
363
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
310
364
pub fn stderr ( ) -> Stderr {
311
- static INSTANCE : Lazy < ReentrantMutex < RefCell < StderrRaw > > > = Lazy :: new ( stderr_init) ;
365
+ static INSTANCE : Lazy < ReentrantMutex < RefCell < Maybe < StderrRaw > > > > = Lazy :: new ( stderr_init) ;
312
366
return Stderr {
313
367
inner : INSTANCE . get ( ) . expect ( "cannot access stderr during shutdown" ) ,
314
368
} ;
315
369
316
- fn stderr_init ( ) -> Arc < ReentrantMutex < RefCell < StderrRaw > > > {
317
- Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( stderr_raw ( ) ) ) )
370
+ fn stderr_init ( ) -> Arc < ReentrantMutex < RefCell < Maybe < StderrRaw > > > > {
371
+ let stderr = match stderr_raw ( ) {
372
+ Ok ( stderr) => Maybe :: Real ( stderr) ,
373
+ _ => Maybe :: Fake ,
374
+ } ;
375
+ Arc :: new ( ReentrantMutex :: new ( RefCell :: new ( stderr) ) )
318
376
}
319
377
}
320
378
0 commit comments