diff options
author | Victor Stinner <vstinner@redhat.com> | 2018-12-20 19:33:51 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-20 19:33:51 (GMT) |
commit | 9a8d1d7562b11969034b92217fe66aab7a951fb6 (patch) | |
tree | ef43389c6be139d7f016e98129c22bc829ea388c /Lib/multiprocessing | |
parent | c5d5dfdb223efb0e668e3f317d31b8b70ae96aa6 (diff) | |
download | cpython-9a8d1d7562b11969034b92217fe66aab7a951fb6.zip cpython-9a8d1d7562b11969034b92217fe66aab7a951fb6.tar.gz cpython-9a8d1d7562b11969034b92217fe66aab7a951fb6.tar.bz2 |
bpo-35424: emit ResourceWarning at multiprocessing.Pool destruction (GH-10974)
multiprocessing.Pool destructor now emits ResourceWarning
if the pool is still running.
Diffstat (limited to 'Lib/multiprocessing')
-rw-r--r-- | Lib/multiprocessing/pool.py | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/Lib/multiprocessing/pool.py b/Lib/multiprocessing/pool.py index 1e26a9b..bfb2769 100644 --- a/Lib/multiprocessing/pool.py +++ b/Lib/multiprocessing/pool.py @@ -13,13 +13,14 @@ __all__ = ['Pool', 'ThreadPool'] # Imports # -import threading -import queue -import itertools import collections +import itertools import os +import queue +import threading import time import traceback +import warnings # If threading is available then ThreadPool should be provided. Therefore # we avoid top-level imports which are liable to fail on some systems. @@ -30,6 +31,7 @@ from . import get_context, TimeoutError # Constants representing the state of a pool # +INIT = "INIT" RUN = "RUN" CLOSE = "CLOSE" TERMINATE = "TERMINATE" @@ -154,11 +156,15 @@ class Pool(object): def __init__(self, processes=None, initializer=None, initargs=(), maxtasksperchild=None, context=None): + # Attributes initialized early to make sure that they exist in + # __del__() if __init__() raises an exception + self._pool = [] + self._state = INIT + self._ctx = context or get_context() self._setup_queues() self._taskqueue = queue.SimpleQueue() self._cache = {} - self._state = RUN self._maxtasksperchild = maxtasksperchild self._initializer = initializer self._initargs = initargs @@ -172,7 +178,6 @@ class Pool(object): raise TypeError('initializer must be a callable') self._processes = processes - self._pool = [] try: self._repopulate_pool() except Exception: @@ -216,6 +221,14 @@ class Pool(object): self._result_handler, self._cache), exitpriority=15 ) + self._state = RUN + + # Copy globals as function locals to make sure that they are available + # during Python shutdown when the Pool is destroyed. + def __del__(self, _warn=warnings.warn, RUN=RUN): + if self._state == RUN: + _warn(f"unclosed running multiprocessing pool {self!r}", + ResourceWarning, source=self) def __repr__(self): cls = self.__class__ |