Skip to content

[3.15] gh-155717: Determine multiprocessing's default start method lazily (GH-159254) - #159271

Merged
gpshead merged 3 commits into
python:3.15from
gpshead:backport-48ddda1-3.15
Oct 12, 2026
Merged

gpshead merged 3 commits into
python:3.15from
gpshead:backport-48ddda1-3.15

Conversation

@gpshead

@gpshead gpshead commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

gh-155827 made import multiprocessing check whether the temporary directory is writeable in order to choose between "forkserver" and "spawn" as the default start method. That check ran at import time and pulled in multiprocessing.util, subprocess, tempfile, shutil and random, noticeably slowing down the import for every program, including ones that never start a process and every spawned child, the fork server and the resource tracker.

The default start method is now determined the first time it is needed instead: on the first get_context(), get_start_method(), get_all_start_methods() or default Process start. multiprocessing.util goes back to importing tempfile only where it is used.

Also include the fix from gh-158410 by Vyron Vasileiadis, along with a test adapted from that PR: when tempfile finds no usable temporary directory at all, the check now reports that instead of raising FileNotFoundError, so that "spawn" is chosen.

The regression was reported, and the lazy approach suggested, by Leandro Damascena in
#155717 (comment)

(cherry picked from commit 48ddda1) backport of #159254

Manual backport notes (3.15)

The automated backport conflicted in Lib/multiprocessing/context.py. main has gh-149879 (the Cygwin test fix), which is not on 3.15 and which changed forkserver to be added to _concrete_contexts conditionally on reduction.HAVE_SEND_HANDLE. 3.15 still lists it unconditionally in the dict literal, and this change rewrites the lines directly below it.

Resolution: kept 3.15's unconditional 'forkserver': ForkServerContext() entry and did not bring over the conditional registration from gh-149879.

We also reword the NEWS entry here, an equivalent rewording has landed on main.

…hod lazily (pythonGH-159254)

pythongh-155827 made `import multiprocessing` check whether the temporary
directory is writeable in order to choose between "forkserver" and
"spawn" as the default start method. That check ran at import time and
pulled in `multiprocessing.util`, `subprocess`, `tempfile`, `shutil`
and `random`, noticeably slowing down the import for every program,
including ones that never start a process and every spawned child,
the fork server and the resource tracker.

The default start method is now determined the first time it is needed
instead: on the first `get_context()`, `get_start_method()`,
`get_all_start_methods()` or default `Process` start.
`multiprocessing.util` goes back to importing `tempfile` only where it
is used.

Also include the fix from pythongh-158410 by Vyron Vasileiadis, along with a
test adapted from that PR: when `tempfile` finds no usable temporary
directory at all, the check now reports that instead of raising
`FileNotFoundError`, so that "spawn" is chosen.

The regression was reported, and the lazy approach suggested, by
Leandro Damascena in
python#155717 (comment)

(cherry picked from commit 48ddda1)

Co-authored-by: Vyron Vasileiadis <hi@fedonman.com>
…hange

Say that the change applies when there is no writable temporary
directory and that starting a process previously failed there.
@read-the-docs-community

Copy link
Copy Markdown

@gpshead
gpshead merged commit 55000c6 into python:3.15 Oct 12, 2026
54 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip news type-bug An unexpected behavior, bug, or error

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant