mirror of
https://github.com/python/cpython.git
synced 2025-10-25 18:54:53 +00:00
bpo-33929: multiprocessing: fix handle leak on race condition (GH-7921)
Fix a race condition in Popen of multiprocessing.popen_spawn_win32. The child process now duplicates the read end of pipe instead of "stealing" it. Previously, the read end of pipe was "stolen" by the child process, but it leaked a handle if the child process had been terminated before it could steal the handle from the parent process.
This commit is contained in:
parent
f15f66d275
commit
2cc9d21fff
4 changed files with 34 additions and 6 deletions
|
|
@ -18,6 +18,12 @@
|
|||
WINEXE = (sys.platform == 'win32' and getattr(sys, 'frozen', False))
|
||||
WINSERVICE = sys.executable.lower().endswith("pythonservice.exe")
|
||||
|
||||
|
||||
def _close_handles(*handles):
|
||||
for handle in handles:
|
||||
_winapi.CloseHandle(handle)
|
||||
|
||||
|
||||
#
|
||||
# We define a Popen class similar to the one from subprocess, but
|
||||
# whose constructor takes a process object as its argument.
|
||||
|
|
@ -32,8 +38,12 @@ class Popen(object):
|
|||
def __init__(self, process_obj):
|
||||
prep_data = spawn.get_preparation_data(process_obj._name)
|
||||
|
||||
# read end of pipe will be "stolen" by the child process
|
||||
# read end of pipe will be duplicated by the child process
|
||||
# -- see spawn_main() in spawn.py.
|
||||
#
|
||||
# bpo-33929: Previously, the read end of pipe was "stolen" by the child
|
||||
# process, but it leaked a handle if the child process had been
|
||||
# terminated before it could steal the handle from the parent process.
|
||||
rhandle, whandle = _winapi.CreatePipe(None, 0)
|
||||
wfd = msvcrt.open_osfhandle(whandle, 0)
|
||||
cmd = spawn.get_command_line(parent_pid=os.getpid(),
|
||||
|
|
@ -56,7 +66,8 @@ def __init__(self, process_obj):
|
|||
self.returncode = None
|
||||
self._handle = hp
|
||||
self.sentinel = int(hp)
|
||||
self.finalizer = util.Finalize(self, _winapi.CloseHandle, (self.sentinel,))
|
||||
self.finalizer = util.Finalize(self, _close_handles,
|
||||
(self.sentinel, int(rhandle)))
|
||||
|
||||
# send information to child
|
||||
set_spawning_popen(self)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue