[Python-checkins] cpython (merge 3.2 -> default): Issue #14252: Fix subprocess.Popen.terminate() to not raise an error under

antoine.pitrou python-checkins at python.org
Sun Mar 11 19:37:53 CET 2012


http://hg.python.org/cpython/rev/f452d7d5470d
changeset: 75525:f452d7d5470d
parent: 75523:8ecd1a1c7dfc
parent: 75524:41b1fe5a75a6
user: Antoine Pitrou <solipsis at pitrou.net>
date: Sun Mar 11 19:33:29 2012 +0100
summary:
 Issue #14252: Fix subprocess.Popen.terminate() to not raise an error under Windows when the child process has already exited.
files:
 Lib/subprocess.py | 10 +++-
 Lib/test/test_subprocess.py | 67 +++++++++++++++++++++++++
 Misc/NEWS | 3 +
 PC/_subprocess.c | 1 +
 4 files changed, 80 insertions(+), 1 deletions(-)
diff --git a/Lib/subprocess.py b/Lib/subprocess.py
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -1162,7 +1162,15 @@
 def terminate(self):
 """Terminates the process
 """
- _subprocess.TerminateProcess(self._handle, 1)
+ try:
+ _subprocess.TerminateProcess(self._handle, 1)
+ except PermissionError:
+ # ERROR_ACCESS_DENIED (winerror 5) is received when the
+ # process already died.
+ rc = _subprocess.GetExitCodeProcess(self._handle)
+ if rc == _subprocess.STILL_ACTIVE:
+ raise
+ self.returncode = rc
 
 kill = terminate
 
diff --git a/Lib/test/test_subprocess.py b/Lib/test/test_subprocess.py
--- a/Lib/test/test_subprocess.py
+++ b/Lib/test/test_subprocess.py
@@ -1078,6 +1078,27 @@
 getattr(p, method)(*args)
 return p
 
+ def _kill_dead_process(self, method, *args):
+ # Do not inherit file handles from the parent.
+ # It should fix failures on some platforms.
+ p = subprocess.Popen([sys.executable, "-c", """if 1:
+ import sys, time
+ sys.stdout.write('x\\n')
+ sys.stdout.flush()
+ """],
+ close_fds=True,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ # Wait for the interpreter to be completely initialized before
+ # sending any signal.
+ p.stdout.read(1)
+ # The process should end after this
+ time.sleep(1)
+ # This shouldn't raise even though the child is now dead
+ getattr(p, method)(*args)
+ p.communicate()
+
 def test_send_signal(self):
 p = self._kill_process('send_signal', signal.SIGINT)
 _, stderr = p.communicate()
@@ -1096,6 +1117,18 @@
 self.assertStderrEqual(stderr, b'')
 self.assertEqual(p.wait(), -signal.SIGTERM)
 
+ def test_send_signal_dead(self):
+ # Sending a signal to a dead process
+ self._kill_dead_process('send_signal', signal.SIGINT)
+
+ def test_kill_dead(self):
+ # Killing a dead process
+ self._kill_dead_process('kill')
+
+ def test_terminate_dead(self):
+ # Terminating a dead process
+ self._kill_dead_process('terminate')
+
 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 @@
 returncode = p.wait()
 self.assertNotEqual(returncode, 0)
 
+ def _kill_dead_process(self, method, *args):
+ p = subprocess.Popen([sys.executable, "-c", """if 1:
+ import sys, time
+ sys.stdout.write('x\\n')
+ sys.stdout.flush()
+ sys.exit(42)
+ """],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ self.addCleanup(p.stdout.close)
+ self.addCleanup(p.stderr.close)
+ self.addCleanup(p.stdin.close)
+ # Wait for the interpreter to be completely initialized before
+ # sending any signal.
+ p.stdout.read(1)
+ # The process should end after this
+ time.sleep(1)
+ # This shouldn't raise even though the child is now dead
+ getattr(p, method)(*args)
+ _, stderr = p.communicate()
+ self.assertStderrEqual(stderr, b'')
+ rc = p.wait()
+ self.assertEqual(rc, 42)
+
 def test_send_signal(self):
 self._kill_process('send_signal', signal.SIGTERM)
 
@@ -1671,6 +1729,15 @@
 def test_terminate(self):
 self._kill_process('terminate')
 
+ def test_send_signal_dead(self):
+ self._kill_dead_process('send_signal', signal.SIGTERM)
+
+ def test_kill_dead(self):
+ self._kill_dead_process('kill')
+
+ def test_terminate_dead(self):
+ self._kill_dead_process('terminate')
+
 
 # The module says:
 # "NB This only works (and is only relevant) for UNIX."
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -22,6 +22,9 @@
 Library
 -------
 
+- Issue #14252: Fix subprocess.Popen.terminate() to not raise an error under
+ Windows when the child process has already exited.
+
 - 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.
diff --git a/PC/_subprocess.c b/PC/_subprocess.c
--- a/PC/_subprocess.c
+++ b/PC/_subprocess.c
@@ -691,6 +691,7 @@
 defint(d, "WAIT_TIMEOUT", WAIT_TIMEOUT);
 defint(d, "CREATE_NEW_CONSOLE", CREATE_NEW_CONSOLE);
 defint(d, "CREATE_NEW_PROCESS_GROUP", CREATE_NEW_PROCESS_GROUP);
+ defint(d, "STILL_ACTIVE", STILL_ACTIVE);
 
 return m;
 }
-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /