Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 84df1e6

Browse files
committed
Merged revisions 81154 via svnmerge from
svn+ssh://[email protected]/python/trunk ........ r81154 | brett.cannon | 2010-05-13 17:21:48 -0700 (Thu, 13 May 2010) | 15 lines subprocess.Popen.__del__ referenced global objects, which is a no-no thanks to interpreter shutdown semantics. Same issue goes for the methods that __del__ called. Now all the methods capture the global objects it needs as default values to private parameters (could have stuck them on the class object itself, but since the objects have nothing directly to do with the class that seemed wrong). There is no test as making one that works is hard. This patch was verified against a consistently failing test in Mercurial's test suite, though, so it has been tested in some regard. Closes issue #5099. Thanks to Mary Stern for the bug report and Gabriel Genellina for writing another patch for the same issue and attempting to write a test. ........
1 parent bbb2d49 commit 84df1e6

1 file changed

Lines changed: 34 additions & 17 deletions

File tree

Lib/subprocess.py

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,6 @@ def __str__(self):
356356

357357

358358
if mswindows:
359-
from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP
360359
import threading
361360
import msvcrt
362361
import _subprocess
@@ -394,6 +393,7 @@ class pywintypes:
394393
"getoutput", "check_output", "CalledProcessError"]
395394

396395
if mswindows:
396+
from _subprocess import CREATE_NEW_CONSOLE, CREATE_NEW_PROCESS_GROUP
397397
__all__.extend(["CREATE_NEW_CONSOLE", "CREATE_NEW_PROCESS_GROUP"])
398398
try:
399399
MAXFD = os.sysconf("SC_OPEN_MAX")
@@ -698,12 +698,12 @@ def _translate_newlines(self, data, encoding):
698698
return data.decode(encoding)
699699

700700

701-
def __del__(self, sys=sys):
701+
def __del__(self, _maxsize=sys.maxsize, _active=_active):
702702
if not self._child_created:
703703
# We didn't get to successfully create a child process.
704704
return
705705
# In case the child hasn't been waited on, check if it's done.
706-
self._internal_poll(_deadstate=sys.maxsize)
706+
self._internal_poll(_deadstate=_maxsize)
707707
if self.returncode is None and _active is not None:
708708
# Child is still running, keep us alive until we can wait on it.
709709
_active.append(self)
@@ -907,13 +907,20 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
907907
errwrite.Close()
908908

909909

910-
def _internal_poll(self, _deadstate=None):
910+
def _internal_poll(self, _deadstate=None,
911+
_WaitForSingleObject=WaitForSingleObject,
912+
_WAIT_OBJECT_0=WAIT_OBJECT_0,
913+
_GetExitCodeProcess=GetExitCodeProcess):
911914
"""Check if child process has terminated. Returns returncode
912-
attribute."""
915+
attribute.
916+
917+
This method is called by __del__, so it can only refer to objects
918+
in its local scope.
919+
920+
"""
913921
if self.returncode is None:
914-
if(_subprocess.WaitForSingleObject(self._handle, 0) ==
915-
_subprocess.WAIT_OBJECT_0):
916-
self.returncode = _subprocess.GetExitCodeProcess(self._handle)
922+
if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0:
923+
self.returncode = _GetExitCodeProcess(self._handle)
917924
return self.returncode
918925

919926

@@ -1252,25 +1259,35 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
12521259
raise child_exception_type(err_msg)
12531260

12541261

1255-
def _handle_exitstatus(self, sts):
1256-
if os.WIFSIGNALED(sts):
1257-
self.returncode = -os.WTERMSIG(sts)
1258-
elif os.WIFEXITED(sts):
1259-
self.returncode = os.WEXITSTATUS(sts)
1262+
def _handle_exitstatus(self, sts, _WIFSIGNALED=os.WIFSIGNALED,
1263+
_WTERMSIG=os.WTERMSIG, _WIFEXITED=os.WIFEXITED,
1264+
_WEXITSTATUS=os.WEXITSTATUS):
1265+
# This method is called (indirectly) by __del__, so it cannot
1266+
# refer to anything outside of its local scope."""
1267+
if _WIFSIGNALED(sts):
1268+
self.returncode = -_WTERMSIG(sts)
1269+
elif _WIFEXITED(sts):
1270+
self.returncode = _WEXITSTATUS(sts)
12601271
else:
12611272
# Should never happen
12621273
raise RuntimeError("Unknown child exit status!")
12631274

12641275

1265-
def _internal_poll(self, _deadstate=None):
1276+
def _internal_poll(self, _deadstate=None, _waitpid=os.waitpid,
1277+
_WNOHANG=os.WNOHANG, _os_error=os.error):
12661278
"""Check if child process has terminated. Returns returncode
1267-
attribute."""
1279+
attribute.
1280+
1281+
This method is called by __del__, so it cannot reference anything
1282+
outside of the local scope (nor can any methods it calls).
1283+
1284+
"""
12681285
if self.returncode is None:
12691286
try:
1270-
pid, sts = os.waitpid(self.pid, os.WNOHANG)
1287+
pid, sts = _waitpid(self.pid, _WNOHANG)
12711288
if pid == self.pid:
12721289
self._handle_exitstatus(sts)
1273-
except os.error:
1290+
except _os_error:
12741291
if _deadstate is not None:
12751292
self.returncode = _deadstate
12761293
return self.returncode

0 commit comments

Comments
 (0)