From 20efceb75790f2a40fad449fd92a6b3d8fe40c8b Mon Sep 17 00:00:00 2001 From: Brian Quinlan Date: Sat, 17 May 2014 13:51:10 -0700 Subject: Issue #21362: concurrent.futures does not validate that max_workers is proper --- Doc/library/concurrent.futures.rst | 2 ++ Lib/concurrent/futures/process.py | 3 +++ Lib/concurrent/futures/thread.py | 3 +++ Lib/test/test_concurrent_futures.py | 7 +++++++ 4 files changed, 15 insertions(+) diff --git a/Doc/library/concurrent.futures.rst b/Doc/library/concurrent.futures.rst index 0495737..08c926a 100644 --- a/Doc/library/concurrent.futures.rst +++ b/Doc/library/concurrent.futures.rst @@ -175,6 +175,8 @@ to a :class:`ProcessPoolExecutor` will result in deadlock. An :class:`Executor` subclass that executes calls asynchronously using a pool of at most *max_workers* processes. If *max_workers* is ``None`` or not given, it will default to the number of processors on the machine. + If *max_workers* is lower or equal to ``0``, then a :exc:`ValueError` + will be raised. .. versionchanged:: 3.3 When one of the worker processes terminates abruptly, a diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py index 07b5225..1299390 100644 --- a/Lib/concurrent/futures/process.py +++ b/Lib/concurrent/futures/process.py @@ -334,6 +334,9 @@ class ProcessPoolExecutor(_base.Executor): if max_workers is None: self._max_workers = os.cpu_count() or 1 else: + if max_workers <= 0: + raise ValueError("max_workers must be greater than 0") + self._max_workers = max_workers # Make the call queue slightly larger than the number of processes to diff --git a/Lib/concurrent/futures/thread.py b/Lib/concurrent/futures/thread.py index f9beb0f..8d6081c 100644 --- a/Lib/concurrent/futures/thread.py +++ b/Lib/concurrent/futures/thread.py @@ -87,6 +87,9 @@ class ThreadPoolExecutor(_base.Executor): max_workers: The maximum number of threads that can be used to execute the given calls. """ + if max_workers <= 0: + raise ValueError("max_workers must be greater than 0") + self._max_workers = max_workers self._work_queue = queue.Queue() self._threads = set() diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index c74b2ca..55254b5 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -425,6 +425,13 @@ class ExecutorTest: self.assertTrue(collected, "Stale reference not collected within timeout.") + def test_max_workers_negative(self): + for number in (0, -1): + with self.assertRaisesRegexp(ValueError, + "max_workers must be greater " + "than 0"): + self.executor_type(max_workers=number) + class ThreadPoolExecutorTest(ThreadPoolMixin, ExecutorTest, unittest.TestCase): def test_map_submits_without_iteration(self): -- cgit v0.12