@@ -397,39 +397,14 @@ class pywintypes:
397397else :
398398 import select
399399 _has_poll = hasattr (select , 'poll' )
400- import fcntl
401- import pickle
402-
403- try :
404- import _posixsubprocess
405- except ImportError :
406- _posixsubprocess = None
407- warnings .warn ("The _posixsubprocess module is not being used. "
408- "Child process reliability may suffer if your "
409- "program uses threads." , RuntimeWarning )
400+ import _posixsubprocess
401+ _create_pipe = _posixsubprocess .cloexec_pipe
410402
411403 # When select or poll has indicated that the file is writable,
412404 # we can write up to _PIPE_BUF bytes without risk of blocking.
413405 # POSIX defines PIPE_BUF as >= 512.
414406 _PIPE_BUF = getattr (select , 'PIPE_BUF' , 512 )
415407
416- _FD_CLOEXEC = getattr (fcntl , 'FD_CLOEXEC' , 1 )
417-
418- def _set_cloexec (fd , cloexec ):
419- old = fcntl .fcntl (fd , fcntl .F_GETFD )
420- if cloexec :
421- fcntl .fcntl (fd , fcntl .F_SETFD , old | _FD_CLOEXEC )
422- else :
423- fcntl .fcntl (fd , fcntl .F_SETFD , old & ~ _FD_CLOEXEC )
424-
425- if _posixsubprocess :
426- _create_pipe = _posixsubprocess .cloexec_pipe
427- else :
428- def _create_pipe ():
429- fds = os .pipe ()
430- _set_cloexec (fds [0 ], True )
431- _set_cloexec (fds [1 ], True )
432- return fds
433408
434409__all__ = ["Popen" , "PIPE" , "STDOUT" , "call" , "check_call" , "getstatusoutput" ,
435410 "getoutput" , "check_output" , "CalledProcessError" , "DEVNULL" ]
@@ -1267,140 +1242,33 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
12671242 errpipe_read , errpipe_write = _create_pipe ()
12681243 try :
12691244 try :
1270-
1271- if _posixsubprocess :
1272- # We must avoid complex work that could involve
1273- # malloc or free in the child process to avoid
1274- # potential deadlocks, thus we do all this here.
1275- # and pass it to fork_exec()
1276-
1277- if env :
1278- env_list = [os .fsencode (k ) + b'=' + os .fsencode (v )
1279- for k , v in env .items ()]
1280- else :
1281- env_list = None # Use execv instead of execve.
1282- executable = os .fsencode (executable )
1283- if os .path .dirname (executable ):
1284- executable_list = (executable ,)
1285- else :
1286- # This matches the behavior of os._execvpe().
1287- executable_list = tuple (
1288- os .path .join (os .fsencode (dir ), executable )
1289- for dir in os .get_exec_path (env ))
1290- fds_to_keep = set (pass_fds )
1291- fds_to_keep .add (errpipe_write )
1292- self .pid = _posixsubprocess .fork_exec (
1293- args , executable_list ,
1294- close_fds , sorted (fds_to_keep ), cwd , env_list ,
1295- p2cread , p2cwrite , c2pread , c2pwrite ,
1296- errread , errwrite ,
1297- errpipe_read , errpipe_write ,
1298- restore_signals , start_new_session , preexec_fn )
1245+ # We must avoid complex work that could involve
1246+ # malloc or free in the child process to avoid
1247+ # potential deadlocks, thus we do all this here.
1248+ # and pass it to fork_exec()
1249+
1250+ if env :
1251+ env_list = [os .fsencode (k ) + b'=' + os .fsencode (v )
1252+ for k , v in env .items ()]
12991253 else :
1300- # Pure Python implementation: It is not thread safe.
1301- # This implementation may deadlock in the child if your
1302- # parent process has any other threads running.
1303-
1304- gc_was_enabled = gc .isenabled ()
1305- # Disable gc to avoid bug where gc -> file_dealloc ->
1306- # write to stderr -> hang. See issue1336
1307- gc .disable ()
1308- try :
1309- self .pid = os .fork ()
1310- except :
1311- if gc_was_enabled :
1312- gc .enable ()
1313- raise
1314- self ._child_created = True
1315- if self .pid == 0 :
1316- # Child
1317- try :
1318- # Close parent's pipe ends
1319- if p2cwrite != - 1 :
1320- os .close (p2cwrite )
1321- if c2pread != - 1 :
1322- os .close (c2pread )
1323- if errread != - 1 :
1324- os .close (errread )
1325- os .close (errpipe_read )
1326-
1327- # Dup fds for child
1328- def _dup2 (a , b ):
1329- # dup2() removes the CLOEXEC flag but
1330- # we must do it ourselves if dup2()
1331- # would be a no-op (issue #10806).
1332- if a == b :
1333- _set_cloexec (a , False )
1334- elif a != - 1 :
1335- os .dup2 (a , b )
1336- _dup2 (p2cread , 0 )
1337- _dup2 (c2pwrite , 1 )
1338- _dup2 (errwrite , 2 )
1339-
1340- # Close pipe fds. Make sure we don't close the
1341- # same fd more than once, or standard fds.
1342- closed = set ()
1343- for fd in [p2cread , c2pwrite , errwrite ]:
1344- if fd > 2 and fd not in closed :
1345- os .close (fd )
1346- closed .add (fd )
1347-
1348- # Close all other fds, if asked for
1349- if close_fds :
1350- fds_to_keep = set (pass_fds )
1351- fds_to_keep .add (errpipe_write )
1352- self ._close_fds (fds_to_keep )
1353-
1354-
1355- if cwd is not None :
1356- os .chdir (cwd )
1357-
1358- # This is a copy of Python/pythonrun.c
1359- # _Py_RestoreSignals(). If that were exposed
1360- # as a sys._py_restoresignals func it would be
1361- # better.. but this pure python implementation
1362- # isn't likely to be used much anymore.
1363- if restore_signals :
1364- signals = ('SIGPIPE' , 'SIGXFZ' , 'SIGXFSZ' )
1365- for sig in signals :
1366- if hasattr (signal , sig ):
1367- signal .signal (getattr (signal , sig ),
1368- signal .SIG_DFL )
1369-
1370- if start_new_session and hasattr (os , 'setsid' ):
1371- os .setsid ()
1372-
1373- if preexec_fn :
1374- preexec_fn ()
1375-
1376- if env is None :
1377- os .execvp (executable , args )
1378- else :
1379- os .execvpe (executable , args , env )
1380-
1381- except :
1382- try :
1383- exc_type , exc_value = sys .exc_info ()[:2 ]
1384- if isinstance (exc_value , OSError ):
1385- errno_num = exc_value .errno
1386- else :
1387- errno_num = 0
1388- message = '%s:%x:%s' % (exc_type .__name__ ,
1389- errno_num , exc_value )
1390- message = message .encode (errors = "surrogatepass" )
1391- os .write (errpipe_write , message )
1392- except Exception :
1393- # We MUST not allow anything odd happening
1394- # above to prevent us from exiting below.
1395- pass
1396-
1397- # This exitcode won't be reported to applications
1398- # so it really doesn't matter what we return.
1399- os ._exit (255 )
1400-
1401- # Parent
1402- if gc_was_enabled :
1403- gc .enable ()
1254+ env_list = None # Use execv instead of execve.
1255+ executable = os .fsencode (executable )
1256+ if os .path .dirname (executable ):
1257+ executable_list = (executable ,)
1258+ else :
1259+ # This matches the behavior of os._execvpe().
1260+ executable_list = tuple (
1261+ os .path .join (os .fsencode (dir ), executable )
1262+ for dir in os .get_exec_path (env ))
1263+ fds_to_keep = set (pass_fds )
1264+ fds_to_keep .add (errpipe_write )
1265+ self .pid = _posixsubprocess .fork_exec (
1266+ args , executable_list ,
1267+ close_fds , sorted (fds_to_keep ), cwd , env_list ,
1268+ p2cread , p2cwrite , c2pread , c2pwrite ,
1269+ errread , errwrite ,
1270+ errpipe_read , errpipe_write ,
1271+ restore_signals , start_new_session , preexec_fn )
14041272 finally :
14051273 # be sure the FD is closed no matter what
14061274 os .close (errpipe_write )
0 commit comments