@@ -19,6 +19,7 @@ use io::{self, BufReader, LineWriter};
1919use sync:: { Arc , Mutex , MutexGuard } ;
2020use sys:: stdio;
2121use sys_common:: remutex:: { ReentrantMutex , ReentrantMutexGuard } ;
22+ use libc;
2223
2324/// Stdout used by print! and println! macros
2425thread_local ! {
@@ -52,7 +53,7 @@ struct StderrRaw(stdio::Stderr);
5253/// handles is **not** available to raw handles returned from this function.
5354///
5455/// 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 ) }
5657
5758/// Constructs a new raw handle to the standard input stream of this process.
5859///
@@ -63,7 +64,7 @@ fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }
6364///
6465/// The returned handle has no external synchronization or buffering layered on
6566/// top.
66- fn stdout_raw ( ) -> StdoutRaw { StdoutRaw ( stdio:: Stdout :: new ( ) ) }
67+ fn stdout_raw ( ) -> io :: Result < StdoutRaw > { stdio:: Stdout :: new ( ) . map ( StdoutRaw ) }
6768
6869/// Constructs a new raw handle to the standard input stream of this process.
6970///
@@ -72,7 +73,7 @@ fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }
7273///
7374/// The returned handle has no external synchronization or buffering layered on
7475/// top.
75- fn stderr_raw ( ) -> StderrRaw { StderrRaw ( stdio:: Stderr :: new ( ) ) }
76+ fn stderr_raw ( ) -> io :: Result < StderrRaw > { stdio:: Stderr :: new ( ) . map ( StderrRaw ) }
7677
7778impl Read for StdinRaw {
7879 fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > { self . 0 . read ( buf) }
@@ -86,6 +87,48 @@ impl Write for StderrRaw {
8687 fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
8788}
8889
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+
89132/// A handle to the standard input stream of a process.
90133///
91134/// Each handle is a shared reference to a global buffer of input data to this
@@ -99,7 +142,7 @@ impl Write for StderrRaw {
99142/// Created by the function `io::stdin()`.
100143#[ stable( feature = "rust1" , since = "1.0.0" ) ]
101144pub struct Stdin {
102- inner : Arc < Mutex < BufReader < StdinRaw > > > ,
145+ inner : Arc < Mutex < BufReader < Maybe < StdinRaw > > > > ,
103146}
104147
105148/// A locked reference to the a `Stdin` handle.
@@ -108,7 +151,7 @@ pub struct Stdin {
108151/// constructed via the `lock` method on `Stdin`.
109152#[ stable( feature = "rust1" , since = "1.0.0" ) ]
110153pub struct StdinLock < ' a > {
111- inner : MutexGuard < ' a , BufReader < StdinRaw > > ,
154+ inner : MutexGuard < ' a , BufReader < Maybe < StdinRaw > > > ,
112155}
113156
114157/// Creates a new handle to the global standard input stream of this process.
@@ -122,20 +165,25 @@ pub struct StdinLock<'a> {
122165/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
123166#[ stable( feature = "rust1" , since = "1.0.0" ) ]
124167pub 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) ;
126169 return Stdin {
127170 inner : INSTANCE . get ( ) . expect ( "cannot access stdin during shutdown" ) ,
128171 } ;
129172
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+
131179 // The default buffer capacity is 64k, but apparently windows
132180 // doesn't like 64k reads on stdin. See #13304 for details, but the
133181 // idea is that on windows we use a slightly smaller buffer that's
134182 // been seen to be acceptable.
135183 Arc :: new ( Mutex :: new ( if cfg ! ( windows) {
136- BufReader :: with_capacity ( 8 * 1024 , stdin_raw ( ) )
184+ BufReader :: with_capacity ( 8 * 1024 , stdin )
137185 } else {
138- BufReader :: new ( stdin_raw ( ) )
186+ BufReader :: new ( stdin )
139187 } ) )
140188 }
141189}
@@ -181,6 +229,7 @@ impl<'a> Read for StdinLock<'a> {
181229 self . inner . read ( buf)
182230 }
183231}
232+
184233#[ stable( feature = "rust1" , since = "1.0.0" ) ]
185234impl < ' a > BufRead for StdinLock < ' a > {
186235 fn fill_buf ( & mut self ) -> io:: Result < & [ u8 ] > { self . inner . fill_buf ( ) }
@@ -215,7 +264,7 @@ pub struct Stdout {
215264 // FIXME: this should be LineWriter or BufWriter depending on the state of
216265 // stdout (tty or not). Note that if this is not line buffered it
217266 // 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 > > > > > ,
219268}
220269
221270/// A locked reference to the a `Stdout` handle.
@@ -224,7 +273,7 @@ pub struct Stdout {
224273/// method on `Stdout`.
225274#[ stable( feature = "rust1" , since = "1.0.0" ) ]
226275pub struct StdoutLock < ' a > {
227- inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < StdoutRaw > > > ,
276+ inner : ReentrantMutexGuard < ' a , RefCell < LineWriter < Maybe < StdoutRaw > > > > ,
228277}
229278
230279/// Constructs a new reference to the standard output of the current process.
@@ -236,13 +285,18 @@ pub struct StdoutLock<'a> {
236285/// The returned handle implements the `Write` trait.
237286#[ stable( feature = "rust1" , since = "1.0.0" ) ]
238287pub 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) ;
240290 return Stdout {
241291 inner : INSTANCE . get ( ) . expect ( "cannot access stdout during shutdown" ) ,
242292 } ;
243293
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) ) ) )
246300 }
247301}
248302
@@ -288,7 +342,7 @@ impl<'a> Write for StdoutLock<'a> {
288342/// For more information, see `stderr`
289343#[ stable( feature = "rust1" , since = "1.0.0" ) ]
290344pub struct Stderr {
291- inner : Arc < ReentrantMutex < RefCell < StderrRaw > > > ,
345+ inner : Arc < ReentrantMutex < RefCell < Maybe < StderrRaw > > > > ,
292346}
293347
294348/// A locked reference to the a `Stderr` handle.
@@ -297,7 +351,7 @@ pub struct Stderr {
297351/// method on `Stderr`.
298352#[ stable( feature = "rust1" , since = "1.0.0" ) ]
299353pub struct StderrLock < ' a > {
300- inner : ReentrantMutexGuard < ' a , RefCell < StderrRaw > > ,
354+ inner : ReentrantMutexGuard < ' a , RefCell < Maybe < StderrRaw > > > ,
301355}
302356
303357/// Constructs a new reference to the standard error stream of a process.
@@ -308,13 +362,17 @@ pub struct StderrLock<'a> {
308362/// The returned handle implements the `Write` trait.
309363#[ stable( feature = "rust1" , since = "1.0.0" ) ]
310364pub 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) ;
312366 return Stderr {
313367 inner : INSTANCE . get ( ) . expect ( "cannot access stderr during shutdown" ) ,
314368 } ;
315369
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) ) )
318376 }
319377}
320378
0 commit comments