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

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