@@ -872,37 +872,6 @@ def __init__(self, args, bufsize=-1, executable=None,
872
872
'and universal_newlines are supplied but '
873
873
'different. Pass one or the other.' )
874
874
875
- # Input and output objects. The general principle is like
876
- # this:
877
- #
878
- # Parent Child
879
- # ------ -----
880
- # p2cwrite ---stdin---> p2cread
881
- # c2pread <--stdout--- c2pwrite
882
- # errread <--stderr--- errwrite
883
- #
884
- # On POSIX, the child objects are file descriptors. On
885
- # Windows, these are Windows file handles. The parent objects
886
- # are file descriptors on both platforms. The parent objects
887
- # are -1 when not using PIPEs. The child objects are -1
888
- # when not redirecting.
889
-
890
- (p2cread , p2cwrite ,
891
- c2pread , c2pwrite ,
892
- errread , errwrite ) = self ._get_handles (stdin , stdout , stderr )
893
-
894
- # We wrap OS handles *before* launching the child, otherwise a
895
- # quickly terminating child could make our fds unwrappable
896
- # (see #8458).
897
-
898
- if _mswindows :
899
- if p2cwrite != - 1 :
900
- p2cwrite = msvcrt .open_osfhandle (p2cwrite .Detach (), 0 )
901
- if c2pread != - 1 :
902
- c2pread = msvcrt .open_osfhandle (c2pread .Detach (), 0 )
903
- if errread != - 1 :
904
- errread = msvcrt .open_osfhandle (errread .Detach (), 0 )
905
-
906
875
self .text_mode = encoding or errors or text or universal_newlines
907
876
if self .text_mode and encoding is None :
908
877
self .encoding = encoding = _text_encoding ()
@@ -1003,6 +972,39 @@ def __init__(self, args, bufsize=-1, executable=None,
1003
972
if uid < 0 :
1004
973
raise ValueError (f"User ID cannot be negative, got { uid } " )
1005
974
975
+ # Input and output objects. The general principle is like
976
+ # this:
977
+ #
978
+ # Parent Child
979
+ # ------ -----
980
+ # p2cwrite ---stdin---> p2cread
981
+ # c2pread <--stdout--- c2pwrite
982
+ # errread <--stderr--- errwrite
983
+ #
984
+ # On POSIX, the child objects are file descriptors. On
985
+ # Windows, these are Windows file handles. The parent objects
986
+ # are file descriptors on both platforms. The parent objects
987
+ # are -1 when not using PIPEs. The child objects are -1
988
+ # when not redirecting.
989
+
990
+ (p2cread , p2cwrite ,
991
+ c2pread , c2pwrite ,
992
+ errread , errwrite ) = self ._get_handles (stdin , stdout , stderr )
993
+
994
+ # From here on, raising exceptions may cause file descriptor leakage
995
+
996
+ # We wrap OS handles *before* launching the child, otherwise a
997
+ # quickly terminating child could make our fds unwrappable
998
+ # (see #8458).
999
+
1000
+ if _mswindows :
1001
+ if p2cwrite != - 1 :
1002
+ p2cwrite = msvcrt .open_osfhandle (p2cwrite .Detach (), 0 )
1003
+ if c2pread != - 1 :
1004
+ c2pread = msvcrt .open_osfhandle (c2pread .Detach (), 0 )
1005
+ if errread != - 1 :
1006
+ errread = msvcrt .open_osfhandle (errread .Detach (), 0 )
1007
+
1006
1008
try :
1007
1009
if p2cwrite != - 1 :
1008
1010
self .stdin = io .open (p2cwrite , 'wb' , bufsize )
@@ -1321,61 +1323,93 @@ def _get_handles(self, stdin, stdout, stderr):
1321
1323
c2pread , c2pwrite = - 1 , - 1
1322
1324
errread , errwrite = - 1 , - 1
1323
1325
1324
- if stdin is None :
1325
- p2cread = _winapi .GetStdHandle (_winapi .STD_INPUT_HANDLE )
1326
- if p2cread is None :
1327
- p2cread , _ = _winapi .CreatePipe (None , 0 )
1328
- p2cread = Handle (p2cread )
1329
- _winapi .CloseHandle (_ )
1330
- elif stdin == PIPE :
1331
- p2cread , p2cwrite = _winapi .CreatePipe (None , 0 )
1332
- p2cread , p2cwrite = Handle (p2cread ), Handle (p2cwrite )
1333
- elif stdin == DEVNULL :
1334
- p2cread = msvcrt .get_osfhandle (self ._get_devnull ())
1335
- elif isinstance (stdin , int ):
1336
- p2cread = msvcrt .get_osfhandle (stdin )
1337
- else :
1338
- # Assuming file-like object
1339
- p2cread = msvcrt .get_osfhandle (stdin .fileno ())
1340
- p2cread = self ._make_inheritable (p2cread )
1341
-
1342
- if stdout is None :
1343
- c2pwrite = _winapi .GetStdHandle (_winapi .STD_OUTPUT_HANDLE )
1344
- if c2pwrite is None :
1345
- _ , c2pwrite = _winapi .CreatePipe (None , 0 )
1346
- c2pwrite = Handle (c2pwrite )
1347
- _winapi .CloseHandle (_ )
1348
- elif stdout == PIPE :
1349
- c2pread , c2pwrite = _winapi .CreatePipe (None , 0 )
1350
- c2pread , c2pwrite = Handle (c2pread ), Handle (c2pwrite )
1351
- elif stdout == DEVNULL :
1352
- c2pwrite = msvcrt .get_osfhandle (self ._get_devnull ())
1353
- elif isinstance (stdout , int ):
1354
- c2pwrite = msvcrt .get_osfhandle (stdout )
1355
- else :
1356
- # Assuming file-like object
1357
- c2pwrite = msvcrt .get_osfhandle (stdout .fileno ())
1358
- c2pwrite = self ._make_inheritable (c2pwrite )
1359
-
1360
- if stderr is None :
1361
- errwrite = _winapi .GetStdHandle (_winapi .STD_ERROR_HANDLE )
1362
- if errwrite is None :
1363
- _ , errwrite = _winapi .CreatePipe (None , 0 )
1364
- errwrite = Handle (errwrite )
1365
- _winapi .CloseHandle (_ )
1366
- elif stderr == PIPE :
1367
- errread , errwrite = _winapi .CreatePipe (None , 0 )
1368
- errread , errwrite = Handle (errread ), Handle (errwrite )
1369
- elif stderr == STDOUT :
1370
- errwrite = c2pwrite
1371
- elif stderr == DEVNULL :
1372
- errwrite = msvcrt .get_osfhandle (self ._get_devnull ())
1373
- elif isinstance (stderr , int ):
1374
- errwrite = msvcrt .get_osfhandle (stderr )
1375
- else :
1376
- # Assuming file-like object
1377
- errwrite = msvcrt .get_osfhandle (stderr .fileno ())
1378
- errwrite = self ._make_inheritable (errwrite )
1326
+ stdin_needsclose = False
1327
+ stdout_needsclose = False
1328
+ stderr_needsclose = False
1329
+
1330
+ try :
1331
+ if stdin is None :
1332
+ p2cread = _winapi .GetStdHandle (_winapi .STD_INPUT_HANDLE )
1333
+ if p2cread is None :
1334
+ stdin_needsclose = True
1335
+ p2cread , _ = _winapi .CreatePipe (None , 0 )
1336
+ p2cread = Handle (p2cread )
1337
+ _winapi .CloseHandle (_ )
1338
+ elif stdin == PIPE :
1339
+ stdin_needsclose = True
1340
+ p2cread , p2cwrite = _winapi .CreatePipe (None , 0 )
1341
+ p2cread , p2cwrite = Handle (p2cread ), Handle (p2cwrite )
1342
+ elif stdin == DEVNULL :
1343
+ p2cread = msvcrt .get_osfhandle (self ._get_devnull ())
1344
+ elif isinstance (stdin , int ):
1345
+ p2cread = msvcrt .get_osfhandle (stdin )
1346
+ else :
1347
+ # Assuming file-like object
1348
+ p2cread = msvcrt .get_osfhandle (stdin .fileno ())
1349
+ p2cread = self ._make_inheritable (p2cread )
1350
+
1351
+ if stdout is None :
1352
+ c2pwrite = _winapi .GetStdHandle (_winapi .STD_OUTPUT_HANDLE )
1353
+ if c2pwrite is None :
1354
+ stdout_needsclose = True
1355
+ _ , c2pwrite = _winapi .CreatePipe (None , 0 )
1356
+ c2pwrite = Handle (c2pwrite )
1357
+ _winapi .CloseHandle (_ )
1358
+ elif stdout == PIPE :
1359
+ stdout_needsclose = True
1360
+ c2pread , c2pwrite = _winapi .CreatePipe (None , 0 )
1361
+ c2pread , c2pwrite = Handle (c2pread ), Handle (c2pwrite )
1362
+ elif stdout == DEVNULL :
1363
+ c2pwrite = msvcrt .get_osfhandle (self ._get_devnull ())
1364
+ elif isinstance (stdout , int ):
1365
+ c2pwrite = msvcrt .get_osfhandle (stdout )
1366
+ else :
1367
+ # Assuming file-like object
1368
+ c2pwrite = msvcrt .get_osfhandle (stdout .fileno ())
1369
+ c2pwrite = self ._make_inheritable (c2pwrite )
1370
+
1371
+ if stderr is None :
1372
+ errwrite = _winapi .GetStdHandle (_winapi .STD_ERROR_HANDLE )
1373
+ if errwrite is None :
1374
+ stderr_needsclose = True
1375
+ _ , errwrite = _winapi .CreatePipe (None , 0 )
1376
+ errwrite = Handle (errwrite )
1377
+ _winapi .CloseHandle (_ )
1378
+ elif stderr == PIPE :
1379
+
7802
stderr_needsclose = True
1380
+ errread , errwrite = _winapi .CreatePipe (None , 0 )
1381
+ errread , errwrite = Handle (errread ), Handle (errwrite )
1382
+ elif stderr == STDOUT :
1383
+ errwrite = c2pwrite
1384
+ elif stderr == DEVNULL :
1385
+ errwrite = msvcrt .get_osfhandle (self ._get_devnull ())
1386
+ elif isinstance (stderr , int ):
1387
+ errwrite = msvcrt .get_osfhandle (stderr )
1388
+ else :
1389
+ # Assuming file-like object
1390
+ errwrite = msvcrt .get_osfhandle (stderr .fileno ())
1391
+ errwrite = self ._make_inheritable (errwrite )
1392
+
1393
+ except BaseException :
1394
+ to_close = []
1395
+ if stdin_needsclose and p2cwrite != - 1 :
1396
+ to_close .append (p2cread )
1397
+ to_close .append (p2cwrite )
1398
+ if stdout_needsclose and p2cwrite != - 1 :
1399
+ to_close .append (c2pread )
1400
+ to_close .append (c2pwrite )
1401
+ if stderr_needsclose and errwrite != - 1 :
1402
+ to_close .append (errread )
1403
+ to_close .append (errwrite )
1404
+ for file in to_close :
1405
+ if isinstance (file , Handle ):
1406
+ file .Close ()
1407
+ else :
1408
+ os .close (file )
1409
+ if hasattr (self , "_devnull" ):
1410
+ os .close (self ._devnull )
1411
+ del self ._devnull
1412
+ raise
1379
1413
1380
1414
return (p2cread , p2cwrite ,
1381
1415
c2pread , c2pwrite ,
@@ -1662,52 +1696,69 @@ def _get_handles(self, stdin, stdout, stderr):
1662
1696
c2pread , c2pwrite = - 1 , - 1
1663
1697
errread , errwrite = - 1 , - 1
1664
1698
1665
- if stdin is None :
1666
- pass
1667
- elif stdin == PIPE :
1668
- p2cread , p2cwrite = os .pipe ()
1669
- if self .pipesize > 0 and hasattr (fcntl , "F_SETPIPE_SZ" ):
1670
- fcntl .fcntl (p2cwrite , fcntl .F_SETPIPE_SZ , self .pipesize )
1671
- elif stdin == DEVNULL :
1672
- p2cread = self ._get_devnull ()
1673
- elif isinstance (stdin , int ):
1674
- p2cread = stdin
1675
- else :
1676
- # Assuming file-like object
1677
- p2cread = stdin .fileno ()
1699
+ try :
1700
+ if stdin is None :
1701
+ pass
1702
+ elif stdin == PIPE :
1703
+ p2cread , p2cwrite = os .pipe ()
1704
+ if self .pipesize > 0 and hasattr (fcntl , "F_SETPIPE_SZ" ):
1705
+ fcntl .fcntl (p2cwrite , fcntl .F_SETPIPE_SZ , self .pipesize )
1706
+ elif stdin == DEVNULL :
1707
+ p2cread = self ._get_devnull ()
1708
+ elif isinstance (stdin , int ):
1709
+ p2cread = stdin
1710
+ else :
1711
+ # Assuming file-like object
1712
+ p2cread = stdin .fileno ()
1678
1713
1679
- if stdout is None :
1680
- pass
1681
- elif stdout == PIPE :
1682
- c2pread , c2pwrite = os .pipe ()
1683
- if self .pipesize > 0 and hasattr (fcntl , "F_SETPIPE_SZ" ):
1684
- fcntl .fcntl (c2pwrite , fcntl .F_SETPIPE_SZ , self .pipesize )
1685
- elif stdout == DEVNULL :
1686
- c2pwrite = self ._get_devnull ()
1687
- elif isinstance (stdout , int ):
1688
- c2pwrite = stdout
1689
- else :
1690
- # Assuming file-like object
1691
- c2pwrite = stdout .fileno ()
1714
+ if stdout is None :
1715
+ pass
1716
+ elif stdout == PIPE :
1717
+ c2pread , c2pwrite = os .pipe ()
1718
+ if self .pipesize > 0 and hasattr (fcntl , "F_SETPIPE_SZ" ):
1719
+ fcntl .fcntl (c2pwrite , fcntl .F_SETPIPE_SZ , self .pipesize )
1720
+ elif stdout == DEVNULL :
1721
+ c2pwrite = self ._get_devnull ()
1722
+ elif isinstance (stdout , int ):
1723
+ c2pwrite = stdout
1724
+ else :
1725
+ # Assuming file-like object
1726
+ c2pwrite = stdout .fileno ()
1692
1727
1693
- if stderr is None :
1694
- pass
1695
- elif stderr == PIPE :
1696
- errread , errwrite = os .pipe ()
1697
- if self .pipesize > 0 and hasattr (fcntl , "F_SETPIPE_SZ" ):
1698
- fcntl .fcntl (errwrite , fcntl .F_SETPIPE_SZ , self .pipesize )
1699
- elif stderr == STDOUT :
1700
- if c2pwrite != - 1 :
1701
- errwrite = c2pwrite
1702
- else : # child's stdout is not set, use parent's stdout
1703
- errwrite = sys .__stdout__ .fileno ()
1704
- elif stderr == DEVNULL :
1705
- errwrite = self ._get_devnull ()
1706
- elif isinstance (stderr , int ):
1707
- errwrite = stderr
1708
- else :
1709
- # Assuming file-like object
1710
- errwrite = stderr .fileno ()
1728
+ if stderr is None :
1729
+ pass
1730
+ elif stderr == PIPE :
1731
+ errread , errwrite = os .pipe ()
1732
+ if self .pipesize > 0 and hasattr (fcntl , "F_SETPIPE_SZ" ):
1733
+ fcntl .fcntl (errwrite , fcntl .F_SETPIPE_SZ , self .pipesize )
1734
+ elif stderr == STDOUT :
1735
+ if c2pwrite != - 1 :
1736
+ errwrite = c2pwrite
1737
+ else : # child's stdout is not set, use parent's stdout
1738
+ errwrite = sys .__stdout__ .fileno ()
1739
+ elif stderr == DEVNULL :
1740
+ errwrite = self ._get_devnull ()
1741
+ elif isinstance (stderr , int ):
1742
+ errwrite = stderr
1743
+ else :
1744
+ # Assuming file-like object
1745
+ errwrite = stderr .fileno ()
1746
+
1747
+ except BaseException :
1748
+ # Close the file descriptors we opened to avoid leakage
1749
+ if stdin == PIPE and p2cwrite != - 1 :
1750
+ os .close (p2cread )
1751
+ os .close (p2cwrite )
1752
+ if stdout == PIPE and c2pwrite != - 1 :
1753
+ os .close (c2pread )
1754
+ os .close (c2pwrite )
1755
+ if stderr == PIPE and errwrite != - 1 :
1756
+ os .close (errread )
1757
+ os .close (errwrite )
1758
+ if hasattr (self , "_devnull" ):
1759
+ os .close (self ._devnull )
1760
+ del self ._devnull
1761
+ raise
1711
1762
1712
1763
return (p2cread , p2cwrite ,
1713
1764
c2pread , c2pwrite ,
0 commit comments