diff options
Diffstat (limited to 'Lib/multiprocessing/popen_spawn_win32.py')
-rw-r--r-- | Lib/multiprocessing/popen_spawn_win32.py | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/Lib/multiprocessing/popen_spawn_win32.py b/Lib/multiprocessing/popen_spawn_win32.py index 3e42e9c..3b92c8a 100644 --- a/Lib/multiprocessing/popen_spawn_win32.py +++ b/Lib/multiprocessing/popen_spawn_win32.py @@ -18,6 +18,12 @@ TERMINATE = 0x10000 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 @@ class Popen(object): 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) |