mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
gh-110036: multiprocessing Popen.terminate() catches PermissionError (#110037)
On Windows, multiprocessing Popen.terminate() now catchs PermissionError and get the process exit code. If the process is still running, raise again the PermissionError. Otherwise, the process terminated as expected: store its exit code.
This commit is contained in:
parent
4e356ad183
commit
bd4518c60c
3 changed files with 17 additions and 4 deletions
|
@ -14,6 +14,7 @@ __all__ = ['Popen']
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Exit code used by Popen.terminate()
|
||||||
TERMINATE = 0x10000
|
TERMINATE = 0x10000
|
||||||
WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
|
WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
|
||||||
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
|
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
|
||||||
|
@ -122,9 +123,15 @@ class Popen(object):
|
||||||
if self.returncode is None:
|
if self.returncode is None:
|
||||||
try:
|
try:
|
||||||
_winapi.TerminateProcess(int(self._handle), TERMINATE)
|
_winapi.TerminateProcess(int(self._handle), TERMINATE)
|
||||||
except OSError:
|
except PermissionError:
|
||||||
if self.wait(timeout=1.0) is None:
|
# ERROR_ACCESS_DENIED (winerror 5) is received when the
|
||||||
|
# process already died.
|
||||||
|
code = _winapi.GetExitCodeProcess(int(self._handle))
|
||||||
|
if code == _winapi.STILL_ACTIVE:
|
||||||
raise
|
raise
|
||||||
|
self.returncode = code
|
||||||
|
else:
|
||||||
|
self.returncode = -signal.SIGTERM
|
||||||
|
|
||||||
kill = terminate
|
kill = terminate
|
||||||
|
|
||||||
|
|
|
@ -557,13 +557,14 @@ class _TestProcess(BaseTestCase):
|
||||||
|
|
||||||
def test_terminate(self):
|
def test_terminate(self):
|
||||||
exitcode = self._kill_process(multiprocessing.Process.terminate)
|
exitcode = self._kill_process(multiprocessing.Process.terminate)
|
||||||
if os.name != 'nt':
|
|
||||||
self.assertEqual(exitcode, -signal.SIGTERM)
|
self.assertEqual(exitcode, -signal.SIGTERM)
|
||||||
|
|
||||||
def test_kill(self):
|
def test_kill(self):
|
||||||
exitcode = self._kill_process(multiprocessing.Process.kill)
|
exitcode = self._kill_process(multiprocessing.Process.kill)
|
||||||
if os.name != 'nt':
|
if os.name != 'nt':
|
||||||
self.assertEqual(exitcode, -signal.SIGKILL)
|
self.assertEqual(exitcode, -signal.SIGKILL)
|
||||||
|
else:
|
||||||
|
self.assertEqual(exitcode, -signal.SIGTERM)
|
||||||
|
|
||||||
def test_cpu_count(self):
|
def test_cpu_count(self):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
On Windows, multiprocessing ``Popen.terminate()`` now catchs
|
||||||
|
:exc:`PermissionError` and get the process exit code. If the process is
|
||||||
|
still running, raise again the :exc:`PermissionError`. Otherwise, the
|
||||||
|
process terminated as expected: store its exit code. Patch by Victor
|
||||||
|
Stinner.
|
Loading…
Add table
Add a link
Reference in a new issue