@@ -1066,6 +1066,34 @@ def wait(self, timeout=None):
1066
1066
pass
1067
1067
raise # resume the KeyboardInterrupt
1068
1068
1069
+ def _close_pipe_fds (self ,
1070
+ p2cread , p2cwrite ,
1071
+ c2pread , c2pwrite ,
1072
+ errread , errwrite ):
1073
+ # self._devnull is not always defined.
1074
+ devnull_fd = getattr (self , '_devnull' , None )
1075
+
1076
+ if _mswindows :
1077
+ if p2cread != - 1 :
1078
+ p2cread .Close ()
1079
+ if c2pwrite != - 1 :
1080
+ c2pwrite .Close ()
1081
+ if errwrite != - 1 :
1082
+ errwrite .Close ()
1083
+ else :
1084
+ if p2cread != - 1 and p2cwrite != - 1 and p2cread != devnull_fd :
1085
+ os .close (p2cread )
1086
+ if c2pwrite != - 1 and c2pread != - 1 and c2pwrite != devnull_fd :
1087
+ os .close (c2pwrite )
1088
+ if errwrite != - 1 and errread != - 1 and errwrite != devnull_fd :
1089
+ os .close (errwrite )
1090
+
1091
+ if devnull_fd is not None :
1092
+ os .close (devnull_fd )
1093
+
1094
+ # Prevent a double close of these handles/fds from __init__ on error.
1095
+ self ._closed_child_pipe_fds = True
1096
+
1069
1097
1070
1098
if _mswindows :
1071
1099
#
@@ -1244,17 +1272,9 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
1244
1272
# output pipe are maintained in this process or else the
1245
1273
# pipe will not close when the child process exits and the
1246
1274
# ReadFile will hang.
1247
- if p2cread != - 1 :
1248
- p2cread .Close ()
1249
- if c2pwrite != - 1 :
1250
- c2pwrite .Close ()
1251
- if errwrite != - 1 :
1252
- errwrite .Close ()
1253
- if hasattr (self , '_devnull' ):
1254
- os .close (self ._devnull )
1255
- # Prevent a double close of these handles/fds from __init__
1256
- # on error.
1257
- self ._closed_child_pipe_fds = True
1275
+ self ._close_pipe_fds (p2cread , p2cwrite ,
1276
+ c2pread , c2pwrite ,
1277
+ errread , errwrite )
1258
1278
1259
1279
# Retain the process handle, but close the thread handle
1260
1280
self ._child_created = True
@@ -1441,7 +1461,10 @@ def _get_handles(self, stdin, stdout, stderr):
1441
1461
errread , errwrite )
1442
1462
1443
1463
1444
- def _posix_spawn (self , args , executable , env , restore_signals ):
1464
+ def _posix_spawn (self , args , executable , env , restore_signals ,
1465
+ p2cread , p2cwrite ,
1466
+ c2pread , c2pwrite ,
1467
+ errread , errwrite ):
1445
1468
"""Execute program using os.posix_spawn()."""
1446
1469
if env is None :
1447
1470
env = os .environ
@@ -1456,7 +1479,26 @@ def _posix_spawn(self, args, executable, env, restore_signals):
1456
1479
sigset .append (signum )
1457
1480
kwargs ['setsigdef' ] = sigset
1458
1481
1482
+ file_actions = []
1483
+ for fd in (p2cwrite , c2pread , errread ):
1484
+ if fd != - 1 :
1485
+ file_actions .append ((os .POSIX_SPAWN_CLOSE , fd ))
1486
+ for fd , fd2 in (
1487
+ (p2cread , 0 ),
1488
+ (c2pwrite , 1 ),
1489
+ (errwrite , 2 ),
1490
+ ):
1491
+ if fd != - 1 :
1492
+ file_actions .append ((os .POSIX_SPAWN_DUP2 , fd , fd2 ))
1493
+ if file_actions :
1494
+ kwargs ['file_actions' ] = file_actions
1495
+
1459
1496
self .pid = os .posix_spawn (executable , args , env , ** kwargs )
1497
+ self ._child_created = True
1498
+
1499
+ self ._close_pipe_fds (p2cread , p2cwrite ,
1500
+ c2pread , c2pwrite ,
1501
+ errread , errwrite )
1460
1502
1461
1503
def _execute_child (self , args , executable , preexec_fn , close_fds ,
1462
1504
pass_fds , cwd , env ,
@@ -1489,11 +1531,14 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
1489
1531
and not close_fds
1490
1532
and not pass_fds
1491
1533
and cwd is None
1492
- and p2cread == p2cwrite == - 1
1493
- and c2pread == c2pwrite == - 1
1494
- and errread == errwrite == - 1
1534
+ and ( p2cread == - 1 or p2cread > 2 )
1535
+ and ( c2pwrite == - 1 or c2pwrite > 2 )
1536
+ and ( errwrite == - 1 or errwrite > 2 )
1495
1537
and not start_new_session ):
1496
- self ._posix_spawn (args , executable , env , restore_signals )
1538
+ self ._posix_spawn (args , executable , env , restore_signals ,
1539
+ p2cread , p2cwrite ,
1540
+ c2pread , c2pwrite ,
1541
+ errread , errwrite )
1497
1542
return
1498
1543
1499
1544
orig_executable = executable
@@ -1548,18 +1593,9 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
1548
1593
# be sure the FD is closed no matter what
1549
1594
os .close (errpipe_write )
1550
1595
1551
- # self._devnull is not always defined.
1552
- devnull_fd = getattr (self , '_devnull' , None )
1553
- if p2cread != - 1 and p2cwrite != - 1 and p2cread != devnull_fd :
1554
- os .close (p2cread )
1555
- if c2pwrite != - 1 and c2pread != - 1 and c2pwrite != devnull_fd :
1556
- os .close (c2pwrite )
1557
- if errwrite != - 1 and errread != - 1 and errwrite != devnull_fd :
1558
- os .close (errwrite )
1559
- if devnull_fd is not None :
1560
- os .close (devnull_fd )
1561
- # Prevent a double close of these fds from __init__ on error.
1562
- self ._closed_child_pipe_fds = True
1596
+ self ._close_pipe_fds (p2cread , p2cwrite ,
1597
+ c2pread , c2pwrite ,
1598
+ errread , errwrite )
1563
1599
1564
1600
# Wait for exec to fail or succeed; possibly raising an
1565
1601
# exception (limited in size)
0 commit comments