cpython: f452d7d5470d (original) (raw)
Mercurial > cpython
changeset 75525:f452d7d5470d
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:33:29 +0100 |
parents | 8ecd1a1c7dfc(current diff)41b1fe5a75a6(diff) |
children | 2b7c39db2150 4b54a686541f fd60aab46733 |
files | Lib/subprocess.py Lib/test/test_subprocess.py Misc/NEWS PC/_subprocess.c |
diffstat | 4 files changed, 80 insertions(+), 1 deletions(-)[+] [-] Lib/subprocess.py 10 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 @@ -1162,7 +1162,15 @@ 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 PermissionError:[](#l1.10)
# ERROR_ACCESS_DENIED (winerror 5) is received when the[](#l1.11)
# process already died.[](#l1.12)
rc = _subprocess.GetExitCodeProcess(self._handle)[](#l1.13)
if rc == _subprocess.STILL_ACTIVE:[](#l1.14)
raise[](#l1.15)
self.returncode = rc[](#l1.16)
--- a/Lib/test/test_subprocess.py +++ b/Lib/test/test_subprocess.py @@ -1078,6 +1078,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() @@ -1096,6 +1117,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 @@ -1662,6 +1695,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) @@ -1671,6 +1729,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 #14223: curses.addch() is no more limited to the range 0-255 when the Python curses is not linked to libncursesw. It was a regression introduced in Python 3.3a1.
--- a/PC/_subprocess.c +++ b/PC/_subprocess.c @@ -691,6 +691,7 @@ PyInit__subprocess() defint(d, "WAIT_TIMEOUT", WAIT_TIMEOUT); defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE); defint(d, "CREATE_NEW_PROCESS_GROUP", CREATE_NEW_PROCESS_GROUP);