Skip to content

Commit

Permalink
pythongh-110036: multiprocessing Popen.terminate() catches Permission…
Browse files Browse the repository at this point in the history
…Error (python#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.
  • Loading branch information
vstinner authored Sep 29, 2023
1 parent 4e356ad commit bd4518c
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 4 deletions.
11 changes: 9 additions & 2 deletions Lib/multiprocessing/popen_spawn_win32.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#
#

# Exit code used by Popen.terminate()
TERMINATE = 0x10000
WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
Expand Down Expand Up @@ -122,9 +123,15 @@ def terminate(self):
if self.returncode is None:
try:
_winapi.TerminateProcess(int(self._handle), TERMINATE)
except OSError:
if self.wait(timeout=1.0) is None:
except PermissionError:
# ERROR_ACCESS_DENIED (winerror 5) is received when the
# process already died.
code = _winapi.GetExitCodeProcess(int(self._handle))
if code == _winapi.STILL_ACTIVE:
raise
self.returncode = code
else:
self.returncode = -signal.SIGTERM

kill = terminate

Expand Down
5 changes: 3 additions & 2 deletions Lib/test/_test_multiprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -557,13 +557,14 @@ def handler(*args):

def test_terminate(self):
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):
exitcode = self._kill_process(multiprocessing.Process.kill)
if os.name != 'nt':
self.assertEqual(exitcode, -signal.SIGKILL)
else:
self.assertEqual(exitcode, -signal.SIGTERM)

def test_cpu_count(self):
try:
Expand Down
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit bd4518c

Please sign in to comment.