Lib/concurrent/futures/process.py
Source:
cpython 3.14 @ ab2d84fe1023/Lib/concurrent/futures/process.py
process.py implements ProcessPoolExecutor. It is the most complex file in concurrent.futures because it must deal with process crashes, a multiprocessing call queue, a result queue, and a management thread that coordinates between the calling process and the worker pool.
Map
| Lines | Symbol | Role |
|---|---|---|
| 1-100 | _WorkItem, _ResultItem | Picklable call/result containers |
| 101-250 | _process_worker, _process_chunk | Entry point run in each worker process |
| 251-480 | _ExecutorManagerThread | Background thread in main process; drains result queue |
| 481-740 | ProcessPoolExecutor | Public executor; submit, map, shutdown |
Reading
Worker entry point
Each worker process runs _process_worker, which loops over a SimpleQueue, calling each _WorkItem and putting a _ResultItem back on the result queue.
# CPython: Lib/concurrent/futures/process.py:101 _process_worker
def _process_worker(call_queue, result_queue, initializer, initargs, max_tasks=None):
if initializer is not None:
try:
initializer(*initargs)
except BaseException:
_base.LOGGER.critical('Exception in initializer:', exc_info=True)
return
while True:
call_item = call_queue.get(block=True)
if call_item is None:
result_queue.put(os.getpid())
return
...
A None sentinel signals the worker to shut down gracefully. Workers send their PID back before exiting so the manager thread can join them.
_ExecutorManagerThread
The manager thread is started by the first submit() call. It runs a select-based loop over three file descriptors: the result queue reader, a wakeup pipe that fires when a worker dies unexpectedly, and a shutdown event.
# CPython: Lib/concurrent/futures/process.py:330 _ExecutorManagerThread.run
def run(self):
while True:
self.add_call_item_to_queue()
result_item, is_broken, cause = self.wait_result_broken_or_wakeup()
if is_broken:
self.terminate_broken(cause)
return
if result_item is not None:
self.process_result_item(result_item)
del result_item
if self.is_shutting_down():
self.flag_executor_dead_and_cleanup()
return
When a worker crashes (is_broken=True), all pending futures receive BrokenProcessPool as their exception.
Pickling constraint
All arguments and return values must be picklable because they cross process boundaries through multiprocessing.SimpleQueue. ThreadPoolExecutor has no such constraint.
gopy notes
Not yet ported. A Go port would use os/exec for worker processes and encoding/gob or JSON for call/result serialization. The wakeup-pipe pattern maps naturally to a chan struct{} in Go.