@@ -397,39 +397,14 @@ class pywintypes:
397
397
else :
398
398
import select
399
399
_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
410
402
411
403
# When select or poll has indicated that the file is writable,
412
404
# we can write up to _PIPE_BUF bytes without risk of blocking.
413
405
# POSIX defines PIPE_BUF as >= 512.
414
406
_PIPE_BUF = getattr (select , 'PIPE_BUF' , 512 )
415
407
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
433
408
434
409
__all__ = ["Popen" , "PIPE" , "STDOUT" , "call" , "check_call" , "getstatusoutput" ,
435
410
"getoutput" , "check_output" , "CalledProcessError" , "DEVNULL" ]
@@ -1267,140 +1242,33 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
1267
1242
errpipe_read , errpipe_write = _create_pipe ()
1268
1243
try :
1269
1244
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 ()]
1299
1253
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 )
1404
1272
finally :
1405
1273
# be sure the FD is closed no matter what
1406
1274
os .close (errpipe_write )
0 commit comments