From d4d6afca5c820a4ba221a8425d06fca5b04ccd99 Mon Sep 17 00:00:00 2001 From: Vyron Vasileiadis Date: Tue, 29 Sep 2026 16:06:38 +0300 Subject: [PATCH] gh-155717: Fix importing multiprocessing with no usable temp directory _has_writeable_tempdir() called tempfile.gettempdir() outside its try/except OSError, so when no temporary directory was usable, import multiprocessing raised FileNotFoundError instead of making spawn the default start method. --- Lib/multiprocessing/util.py | 5 ++++- Lib/test/_test_multiprocessing.py | 32 +++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index cf7e0b2990598b..73118df5bec5fa 100644 --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -234,7 +234,10 @@ def _has_writeable_tempdir(): # # See: https://github.com/python/cpython/issues/155717. - path = _get_base_temp_dir() + try: + path = _get_base_temp_dir() + except OSError: + return False if path is None: return False diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index 46ed8843fcd051..cd27c7be39cb93 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -6514,6 +6514,38 @@ def test_forkserver_requires_writeable_tempdir(self, mode): _, out, err = script_helper.assert_python_ok('-c', cmd, TMPDIR=TMPDIR) self.assertEqual(out.decode().strip(), "spawn") + @unittest.skipIf(os.name == "nt", "requires POSIX") + @support.requires_non_root_user + def test_import_without_usable_tempdir(self): + # Importing multiprocessing must not fail when tempfile finds no + # usable temporary directory at all, and the default start method + # must then be 'spawn'. + # + # See https://github.com/python/cpython/issues/155717. + + cmd = '''if 1: + import os, tempfile + # Make TMPDIR the only candidate, so that tempfile.gettempdir() + # raises FileNotFoundError instead of falling back to /tmp. + tempfile._candidate_tempdir_list = lambda: [os.environ["TMPDIR"]] + try: + tempfile.gettempdir() + except FileNotFoundError: + pass + else: + raise AssertionError("TMPDIR is usable") + + import multiprocessing + if __name__ == "__main__": + print(multiprocessing.get_start_method()) + ''' + + with support.os_helper.temp_dir() as root: + TMPDIR = pathlib.Path(root, "TMPDIR") + TMPDIR.mkdir(mode=os.R_OK | os.X_OK) + _, out, err = script_helper.assert_python_ok('-c', cmd, TMPDIR=TMPDIR) + self.assertEqual(out.decode().strip(), "spawn") + @unittest.skipIf(sys.platform == "win32", "test semantics don't make sense on Windows")