Skip to content

On Windows, creating a multiprocessing pool leaks handles #154208

Description

@vstinner

Example:

import ctypes.wintypes
import gc
import multiprocessing.pool

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

kernel32.GetCurrentProcess.argtypes = ()
kernel32.GetCurrentProcess.restype = ctypes.wintypes.HANDLE

kernel32.GetProcessHandleCount.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.LPDWORD)
kernel32.GetProcessHandleCount.restype = ctypes.wintypes.BOOL

def handle_count():
    # Pseudo-handle that doesn't need to be closed
    hproc = kernel32.GetCurrentProcess()

    handle_count = ctypes.wintypes.DWORD()
    if not kernel32.GetProcessHandleCount(hproc, ctypes.byref(handle_count)):
        raise ctypes.WinError(ctypes.get_last_error())

    return handle_count.value

def func():
    pool = multiprocessing.pool.Pool(1)
    pool.terminate()
    pool.join()
    pool.close()
    pool = None
    gc.collect()

def main():
    print("Initial handle count:", handle_count())
    for _ in range(4):
        func()
        print("Handle count:", handle_count())

if __name__ == "__main__":
    main()

Output with Python 3.16 on Windows:

Initial handle count: 116
Handle count: 123
Handle count: 127
Handle count: 131
Handle count: 135

I discovered the issue while working on PR gh-154140 which detects leaks of Windows handles in the Python test suite.

Metadata

Metadata

Assignees

No one assigned

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions