cpython: 41b1fe5a75a6 (original) (raw)
Mercurial > cpython
changeset 75524:41b1fe5a75a6 3.2
Issue #14252: Fix subprocess.Popen.terminate() to not raise an error under Windows when the child process has already exited. [#14252]
Antoine Pitrou solipsis@pitrou.net | |
---|---|
date | Sun, 11 Mar 2012 19:29:12 +0100 |
parents | a5b073b1cfea |
children | f452d7d5470d 3f15c069454d 15550b5777b9 |
files | Lib/subprocess.py Lib/test/test_subprocess.py Misc/NEWS PC/_subprocess.c |
diffstat | 4 files changed, 82 insertions(+), 1 deletions(-)[+] [-] Lib/subprocess.py 12 Lib/test/test_subprocess.py 67 Misc/NEWS 3 PC/_subprocess.c 1 |
line wrap: on
line diff
--- a/Lib/subprocess.py +++ b/Lib/subprocess.py @@ -1075,7 +1075,17 @@ class Popen(object): def terminate(self): """Terminates the process """
_subprocess.TerminateProcess(self._handle, 1)[](#l1.7)
try:[](#l1.8)
_subprocess.TerminateProcess(self._handle, 1)[](#l1.9)
except OSError as e:[](#l1.10)
# ERROR_ACCESS_DENIED (winerror 5) is received when the[](#l1.11)
# process already died.[](#l1.12)
if e.winerror != 5:[](#l1.13)
raise[](#l1.14)
rc = _subprocess.GetExitCodeProcess(self._handle)[](#l1.15)
if rc == _subprocess.STILL_ACTIVE:[](#l1.16)
raise[](#l1.17)
self.returncode = rc[](#l1.18)
--- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -989,6 +989,27 @@ class POSIXProcessTestCase(BaseTestCase) getattr(p, method)(*args) return p
- def _kill_dead_process(self, method, *args):
# Do not inherit file handles from the parent.[](#l2.8)
# It should fix failures on some platforms.[](#l2.9)
p = subprocess.Popen([sys.executable, "-c", """if 1:[](#l2.10)
import sys, time[](#l2.11)
sys.stdout.write('x\\n')[](#l2.12)
sys.stdout.flush()[](#l2.13)
"""],[](#l2.14)
close_fds=True,[](#l2.15)
stdin=subprocess.PIPE,[](#l2.16)
stdout=subprocess.PIPE,[](#l2.17)
stderr=subprocess.PIPE)[](#l2.18)
# Wait for the interpreter to be completely initialized before[](#l2.19)
# sending any signal.[](#l2.20)
p.stdout.read(1)[](#l2.21)
# The process should end after this[](#l2.22)
time.sleep(1)[](#l2.23)
# This shouldn't raise even though the child is now dead[](#l2.24)
getattr(p, method)(*args)[](#l2.25)
p.communicate()[](#l2.26)
+ def test_send_signal(self): p = self._kill_process('send_signal', signal.SIGINT) _, stderr = p.communicate() @@ -1007,6 +1028,18 @@ class POSIXProcessTestCase(BaseTestCase) self.assertStderrEqual(stderr, b'') self.assertEqual(p.wait(), -signal.SIGTERM)
- def test_send_signal_dead(self):
# Sending a signal to a dead process[](#l2.36)
self._kill_dead_process('send_signal', signal.SIGINT)[](#l2.37)
- def test_kill_dead(self):
# Killing a dead process[](#l2.40)
self._kill_dead_process('kill')[](#l2.41)
- def test_terminate_dead(self):
# Terminating a dead process[](#l2.44)
self._kill_dead_process('terminate')[](#l2.45)
+ def check_close_std_fds(self, fds): # Issue #9905: test that subprocess pipes still work properly with # some standard fds closed @@ -1568,6 +1601,31 @@ class Win32ProcessTestCase(BaseTestCase) returncode = p.wait() self.assertNotEqual(returncode, 0)
- def _kill_dead_process(self, method, *args):
p = subprocess.Popen([sys.executable, "-c", """if 1:[](#l2.55)
import sys, time[](#l2.56)
sys.stdout.write('x\\n')[](#l2.57)
sys.stdout.flush()[](#l2.58)
sys.exit(42)[](#l2.59)
"""],[](#l2.60)
stdin=subprocess.PIPE,[](#l2.61)
stdout=subprocess.PIPE,[](#l2.62)
stderr=subprocess.PIPE)[](#l2.63)
self.addCleanup(p.stdout.close)[](#l2.64)
self.addCleanup(p.stderr.close)[](#l2.65)
self.addCleanup(p.stdin.close)[](#l2.66)
# Wait for the interpreter to be completely initialized before[](#l2.67)
# sending any signal.[](#l2.68)
p.stdout.read(1)[](#l2.69)
# The process should end after this[](#l2.70)
time.sleep(1)[](#l2.71)
# This shouldn't raise even though the child is now dead[](#l2.72)
getattr(p, method)(*args)[](#l2.73)
_, stderr = p.communicate()[](#l2.74)
self.assertStderrEqual(stderr, b'')[](#l2.75)
rc = p.wait()[](#l2.76)
self.assertEqual(rc, 42)[](#l2.77)
+ def test_send_signal(self): self._kill_process('send_signal', signal.SIGTERM) @@ -1577,6 +1635,15 @@ class Win32ProcessTestCase(BaseTestCase) def test_terminate(self): self._kill_process('terminate')
The module says:
"NB This only works (and is only relevant) for UNIX."
--- a/Misc/NEWS +++ b/Misc/NEWS @@ -22,6 +22,9 @@ Core and Builtins Library ------- +- Issue #14252: Fix subprocess.Popen.terminate() to not raise an error under
- Issue #14195: An issue that caused weakref.WeakSet instances to incorrectly return True for a WeakSet instance 'a' in both 'a < a' and 'a > a' has been fixed.
--- a/PC/_subprocess.c +++ b/PC/_subprocess.c @@ -684,6 +684,7 @@ PyInit__subprocess() defint(d, "WAIT_OBJECT_0", WAIT_OBJECT_0); defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE); defint(d, "CREATE_NEW_PROCESS_GROUP", CREATE_NEW_PROCESS_GROUP);