summaryrefslogtreecommitdiffstats
path: root/Lib/concurrent
diff options
context:
space:
mode:
authorBrian Quinlan <brian@sweetapp.com>2019-05-08 18:04:53 (GMT)
committerSteve Dower <steve.dower@python.org>2019-05-08 18:04:53 (GMT)
commit39889864c09741909da4ec489459d0197ea8f1fc (patch)
tree08f7745e5ca5554a14f6b583a4ee8d345d3fe4b7 /Lib/concurrent
parentb9b08cd948de97d756a199b60becce8397a8c882 (diff)
downloadcpython-39889864c09741909da4ec489459d0197ea8f1fc.zip
cpython-39889864c09741909da4ec489459d0197ea8f1fc.tar.gz
cpython-39889864c09741909da4ec489459d0197ea8f1fc.tar.bz2
bpo-26903: Limit ProcessPoolExecutor to 61 workers on Windows (GH-13132)
Co-Authored-By: brianquinlan <brian@sweetapp.com>
Diffstat (limited to 'Lib/concurrent')
-rw-r--r--Lib/concurrent/futures/process.py14
1 files changed, 14 insertions, 0 deletions
diff --git a/Lib/concurrent/futures/process.py b/Lib/concurrent/futures/process.py
index d7e2478..dd14eae 100644
--- a/Lib/concurrent/futures/process.py
+++ b/Lib/concurrent/futures/process.py
@@ -57,6 +57,7 @@ import threading
import weakref
from functools import partial
import itertools
+import sys
import traceback
# Workers are created as daemon threads and processes. This is done to allow the
@@ -109,6 +110,12 @@ def _python_exit():
EXTRA_QUEUED_CALLS = 1
+# On Windows, WaitForMultipleObjects is used to wait for processes to finish.
+# It can wait on, at most, 63 objects. There is an overhead of two objects:
+# - the result queue reader
+# - the thread wakeup reader
+_MAX_WINDOWS_WORKERS = 63 - 2
+
# Hack to embed stringification of remote traceback in local traceback
class _RemoteTraceback(Exception):
@@ -505,9 +512,16 @@ class ProcessPoolExecutor(_base.Executor):
if max_workers is None:
self._max_workers = os.cpu_count() or 1
+ if sys.platform == 'win32':
+ self._max_workers = min(_MAX_WINDOWS_WORKERS,
+ self._max_workers)
else:
if max_workers <= 0:
raise ValueError("max_workers must be greater than 0")
+ elif (sys.platform == 'win32' and
+ max_workers > _MAX_WINDOWS_WORKERS):
+ raise ValueError(
+ f"max_workers must be <= {_MAX_WINDOWS_WORKERS}")
self._max_workers = max_workers