Skip to content

Off-by-one error in Lib/multiprocessing/util.py _SUN_PATH_MAX calculation causes forkserver OSError: AF_UNIX path too long #140734

@zmedico

Description

@zmedico

Bug report

Bug description:

This test case fails with OSError: AF_UNIX path too long on Linux if the adjustment argument is 0, and succeeds if the adjustment argument is 1:

#!/usr/bin/env python3.14 import multiprocessing import os import sys from multiprocessing.util import _SUN_PATH_MAX def target(): print("fork was successful") def run_proc(adjustment): os.environ["TMPDIR"] = ( "/tmp/" + (_SUN_PATH_MAX - len("/tmp/") - 14 - 14 - adjustment) * "X" ) os.makedirs(os.environ["TMPDIR"], exist_ok=True) print("TMPDIR length", len(os.environ["TMPDIR"])) proc = multiprocessing.Process(target=target) proc.start() try: proc.join() finally: try: os.rmdir(os.environ["TMPDIR"]) except OSError: pass def main(argv): adjustment = int(argv[1]) run_proc(adjustment) if __name__ == "__main__": main(sys.argv)

Test results:

$ for adjustment in 0 1; do ./forkserver_bug.py $adjustment; done TMPDIR length 80 Traceback (most recent call last): File "/home/zmedico/./forkserver_bug.py", line 37, in <module> main(sys.argv) ~~~~^^^^^^^^^^ File "/home/zmedico/./forkserver_bug.py", line 33, in main run_proc(adjustment) ~~~~~~~~^^^^^^^^^^^^ File "/home/zmedico/./forkserver_bug.py", line 21, in run_proc proc.start() ~~~~~~~~~~^^ File "/usr/lib/python3.14/multiprocessing/process.py", line 121, in start self._popen = self._Popen(self) ~~~~~~~~~~~^^^^^^ File "/usr/lib/python3.14/multiprocessing/context.py", line 224, in _Popen return _default_context.get_context().Process._Popen(process_obj) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ File "/usr/lib/python3.14/multiprocessing/context.py", line 300, in _Popen return Popen(process_obj) File "/usr/lib/python3.14/multiprocessing/popen_forkserver.py", line 35, in __init__ super().__init__(process_obj) ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^ File "/usr/lib/python3.14/multiprocessing/popen_fork.py", line 20, in __init__ self._launch(process_obj) ~~~~~~~~~~~~^^^^^^^^^^^^^ File "/usr/lib/python3.14/multiprocessing/popen_forkserver.py", line 51, in _launch self.sentinel, w = forkserver.connect_to_new_process(self._fds) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^ File "/usr/lib/python3.14/multiprocessing/forkserver.py", line 89, in connect_to_new_process self.ensure_running() ~~~~~~~~~~~~~~~~~~~^^ File "/usr/lib/python3.14/multiprocessing/forkserver.py", line 157, in ensure_running listener.bind(address) ~~~~~~~~~~~~~^^^^^^^^^ OSError: AF_UNIX path too long TMPDIR length 79 fork was successful

I think this would fix it for Linux, but I'm not sure about other platforms:

--- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -176,5 +176,5 @@ def _get_base_temp_dir(tempfile): # len(base_tempdir + '/pymp-XXXXXXXX' + '/sock-XXXXXXXX') sun_path_len = len(base_tempdir) + 14 + 14 - if sun_path_len <= _SUN_PATH_MAX: + if sun_path_len < _SUN_PATH_MAX: return base_tempdir # Fallback to the default system-wide temporary directory. @@ -202,5 +202,5 @@ def _get_base_temp_dir(tempfile): warn("Ignoring user-defined temporary directory: %s", base_tempdir) # at most max(map(len, dirlist)) + 14 + 14 = 36 characters - assert len(base_system_tempdir) + 14 + 14 <= _SUN_PATH_MAX + assert len(base_system_tempdir) + 14 + 14 < _SUN_PATH_MAX return base_system_tempdir

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

Labels

3.13bugs and security fixes3.14bugs and security fixes3.15new features, bugs and security fixesOS-linuxstdlibStandard Library Python modules in the Lib/ directorytopic-multiprocessingtype-bugAn unexpected behavior, bug, or error

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions