@@ -29,18 +29,43 @@ pub struct AnonPipe {
2929 inner : Handle ,
3030}
3131
32- pub fn anon_pipe ( ) -> io:: Result < ( AnonPipe , AnonPipe ) > {
32+ pub struct Pipes {
33+ pub ours : AnonPipe ,
34+ pub theirs : AnonPipe ,
35+ }
36+
37+ /// Although this looks similar to `anon_pipe` in the Unix module it's actually
38+ /// subtly different. Here we'll return two pipes in the `Pipes` return value,
39+ /// but one is intended for "us" where as the other is intended for "someone
40+ /// else".
41+ ///
42+ /// Currently the only use case for this function is pipes for stdio on
43+ /// processes in the standard library, so "ours" is the one that'll stay in our
44+ /// process whereas "theirs" will be inherited to a child.
45+ ///
46+ /// The ours/theirs pipes are *not* specifically readable or writable. Each
47+ /// one only supports a read or a write, but which is which depends on the
48+ /// boolean flag given. If `ours_readable` is true then `ours` is readable where
49+ /// `theirs` is writable. Conversely if `ours_readable` is false then `ours` is
50+ /// writable where `theirs` is readable.
51+ ///
52+ /// Also note that the `ours` pipe is always a handle opened up in overlapped
53+ /// mode. This means that technically speaking it should only ever be used
54+ /// with `OVERLAPPED` instances, but also works out ok if it's only ever used
55+ /// once at a time (which we do indeed guarantee).
56+ pub fn anon_pipe ( ours_readable : bool ) -> io:: Result < Pipes > {
3357 // Note that we specifically do *not* use `CreatePipe` here because
3458 // unfortunately the anonymous pipes returned do not support overlapped
35- // operations.
36- //
37- // Instead, we create a "hopefully unique" name and create a named pipe
38- // which has overlapped operations enabled.
59+ // operations. Instead, we create a "hopefully unique" name and create a
60+ // named pipe which has overlapped operations enabled.
3961 //
40- // Once we do this, we connect do it as usual via `CreateFileW`, and then we
41- // return those reader/writer halves.
62+ // Once we do this, we connect do it as usual via `CreateFileW`, and then
63+ // we return those reader/writer halves. Note that the `ours` pipe return
64+ // value is always the named pipe, whereas `theirs` is just the normal file.
65+ // This should hopefully shield us from child processes which assume their
66+ // stdout is a named pipe, which would indeed be odd!
4267 unsafe {
43- let reader ;
68+ let ours ;
4469 let mut name;
4570 let mut tries = 0 ;
4671 let mut reject_remote_clients_flag = c:: PIPE_REJECT_REMOTE_CLIENTS ;
@@ -54,11 +79,16 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
5479 . encode_wide ( )
5580 . chain ( Some ( 0 ) )
5681 . collect :: < Vec < _ > > ( ) ;
82+ let mut flags = c:: FILE_FLAG_FIRST_PIPE_INSTANCE |
83+ c:: FILE_FLAG_OVERLAPPED ;
84+ if ours_readable {
85+ flags |= c:: PIPE_ACCESS_INBOUND ;
86+ } else {
87+ flags |= c:: PIPE_ACCESS_OUTBOUND ;
88+ }
5789
5890 let handle = c:: CreateNamedPipeW ( wide_name. as_ptr ( ) ,
59- c:: PIPE_ACCESS_INBOUND |
60- c:: FILE_FLAG_FIRST_PIPE_INSTANCE |
61- c:: FILE_FLAG_OVERLAPPED ,
91+ flags,
6292 c:: PIPE_TYPE_BYTE |
6393 c:: PIPE_READMODE_BYTE |
6494 c:: PIPE_WAIT |
@@ -101,21 +131,28 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
101131 }
102132 return Err ( err)
103133 }
104- reader = Handle :: new ( handle) ;
134+ ours = Handle :: new ( handle) ;
105135 break
106136 }
107137
108- // Connect to the named pipe we just created in write-only mode (also
109- // overlapped for async I/O below).
138+ // Connect to the named pipe we just created. This handle is going to be
139+ // returned in `theirs`, so if `ours` is readable we want this to be
140+ // writable, otherwise if `ours` is writable we want this to be
141+ // readable.
142+ //
143+ // Additionally we don't enable overlapped mode on this because most
144+ // client processes aren't enabled to work with that.
110145 let mut opts = OpenOptions :: new ( ) ;
111- opts. write ( true ) ;
112- opts. read ( false ) ;
146+ opts. write ( ours_readable ) ;
147+ opts. read ( !ours_readable ) ;
113148 opts. share_mode ( 0 ) ;
114- opts. attributes ( c:: FILE_FLAG_OVERLAPPED ) ;
115- let writer = File :: open ( Path :: new ( & name) , & opts) ?;
116- let writer = AnonPipe { inner : writer. into_handle ( ) } ;
149+ let theirs = File :: open ( Path :: new ( & name) , & opts) ?;
150+ let theirs = AnonPipe { inner : theirs. into_handle ( ) } ;
117151
118- Ok ( ( AnonPipe { inner : reader } , AnonPipe { inner : writer. into_handle ( ) } ) )
152+ Ok ( Pipes {
153+ ours : AnonPipe { inner : ours } ,
154+ theirs : AnonPipe { inner : theirs. into_handle ( ) } ,
155+ } )
119156 }
120157}
121158
0 commit comments