diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index cf7e0b2990598b7..73118df5bec5fa0 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 46ed8843fcd0519..cd27c7be39cb937 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")