@@ -1066,6 +1066,34 @@ def wait(self, timeout=None):
10661066 pass
10671067 raise # resume the KeyboardInterrupt
10681068
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+
10691097
10701098 if _mswindows :
10711099 #
@@ -1244,17 +1272,9 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
12441272 # output pipe are maintained in this process or else the
12451273 # pipe will not close when the child process exits and the
12461274 # 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 )
12581278
12591279 # Retain the process handle, but close the thread handle
12601280 self ._child_created = True
@@ -1441,7 +1461,10 @@ def _get_handles(self, stdin, stdout, stderr):
14411461 errread , errwrite )
14421462
14431463
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 ):
14451468 """Execute program using os.posix_spawn()."""
14461469 if env is None :
14471470 env = os .environ
@@ -1456,7 +1479,26 @@ def _posix_spawn(self, args, executable, env, restore_signals):
14561479 sigset .append (signum )
14571480 kwargs ['setsigdef' ] = sigset
14581481
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+
14591496 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 )
14601502
14611503 def _execute_child (self , args , executable , preexec_fn , close_fds ,
14621504 pass_fds , cwd , env ,
@@ -1489,11 +1531,14 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
14891531 and not close_fds
14901532 and not pass_fds
14911533 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 )
14951537 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 )
14971542 return
14981543
14991544 orig_executable = executable
@@ -1548,18 +1593,9 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
15481593 # be sure the FD is closed no matter what
15491594 os .close (errpipe_write )
15501595
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 )
15631599
15641600 # Wait for exec to fail or succeed; possibly raising an
15651601 # exception (limited in size)
0 commit comments