@@ -213,6 +213,9 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None):
213
213
self ._loop = loop
214
214
self ._pipe = pipe
215
215
self ._fileno = pipe .fileno ()
216
+ mode = os .fstat (self ._fileno ).st_mode
217
+ if not (stat .S_ISFIFO (mode ) or stat .S_ISSOCK (mode )):
218
+ raise ValueError ("Pipe transport is for pipes/sockets only." )
216
219
_set_nonblocking (self ._fileno )
217
220
self ._protocol = protocol
218
221
self ._closing = False
@@ -275,21 +278,29 @@ def __init__(self, loop, pipe, protocol, waiter=None, extra=None):
275
278
self ._loop = loop
276
279
self ._pipe = pipe
277
280
self ._fileno = pipe .fileno ()
278
- if not stat .S_ISFIFO (os .fstat (self ._fileno ).st_mode ):
279
- raise ValueError ("Pipe transport is for pipes only." )
281
+ mode = os .fstat (self ._fileno ).st_mode
282
+ is_socket = stat .S_ISSOCK (mode )
283
+ is_pipe = stat .S_ISFIFO (mode )
284
+ if not (is_socket or is_pipe ):
285
+ raise ValueError ("Pipe transport is for pipes/sockets only." )
280
286
_set_nonblocking (self ._fileno )
281
287
self ._protocol = protocol
282
288
self ._buffer = []
283
289
self ._conn_lost = 0
284
290
self ._closing = False # Set when close() or write_eof() called.
285
- self ._loop .add_reader (self ._fileno , self ._read_ready )
291
+
292
+ # On AIX, the reader trick only works for sockets.
293
+ # On other platforms it works for pipes and sockets.
294
+ # (Exception: OS X 10.4? Issue #19294.)
295
+ if is_socket or not sys .platform .startswith ("aix" ):
296
+ self ._loop .add_reader (self ._fileno , self ._read_ready )
286
297
287
298
self ._loop .call_soon (self ._protocol .connection_made , self )
288
299
if waiter is not None :
289
300
self ._loop .call_soon (waiter .set_result , None )
290
301
291
302
def _read_ready (self ):
292
- # pipe was closed by peer
303
+ # Pipe was closed by peer.
293
304
self ._close ()
294
305
295
306
def write (self , data ):
@@ -435,8 +446,15 @@ def __init__(self, loop, protocol, args, shell,
435
446
self ._loop = loop
436
447
437
448
self ._pipes = {}
449
+ stdin_w = None
438
450
if stdin == subprocess .PIPE :
439
451
self ._pipes [STDIN ] = None
452
+ # Use a socket pair for stdin, since not all platforms
453
+ # support selecting read events on the write end of a
454
+ # socket (which we use in order to detect closing of the
455
+ # other end). Notably this is needed on AIX, and works
456
+ # just fine on other platforms.
457
+ stdin , stdin_w = self ._loop ._socketpair ()
440
458
if stdout == subprocess .PIPE :
441
459
self ._pipes [STDOUT ] = None
442
460
if stderr == subprocess .PIPE :
@@ -448,6 +466,9 @@ def __init__(self, loop, protocol, args, shell,
448
466
self ._proc = subprocess .Popen (
449
467
args , shell = shell , stdin = stdin , stdout = stdout , stderr = stderr ,
450
468
universal_newlines = False , bufsize = bufsize , ** kwargs )
469
+ if stdin_w is not None :
470
+ stdin .close ()
471
+ self ._proc .stdin = open (stdin_w .detach (), 'rb' , buffering = bufsize )
451
472
self ._extra ['subprocess' ] = self ._proc
452
473
453
474
def close (self ):
0 commit comments