diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py index cabf548ec38f3d..1e0f14eb3a1888 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -753,10 +753,14 @@ def temp_dir(path=None, quiet=False): raise warnings.warn('tests may fail, unable to create temp dir: ' + path, RuntimeWarning, stacklevel=3) + if dir_created: + pid = os.getpid() try: yield path finally: - if dir_created: + # In case the process forks, let only the parent remove the + # directory. The child has a diffent process id. (bpo-30028) + if dir_created and pid == os.getpid(): rmtree(path) @contextlib.contextmanager diff --git a/Lib/test/test_test_support.py b/Lib/test/test_test_support.py index 1b62ac99028e3f..421a9ef8892f80 100644 --- a/Lib/test/test_test_support.py +++ b/Lib/test/test_test_support.py @@ -6,8 +6,10 @@ import unittest import socket import tempfile +import textwrap import errno from test import support +from test.support import script_helper TESTFN = support.TESTFN @@ -176,6 +178,34 @@ def test_temp_dir__existing_dir__quiet_true(self): expected = ['tests may fail, unable to create temp dir: ' + path] self.assertEqual(warnings, expected) + @unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork") + def test_temp_dir__forked_child(self): + """Test that a forked child process does not remove the directory.""" + # See bpo-30028 for details. + # Run the test as an external script, because it uses fork. + script_helper.assert_python_ok("-c", textwrap.dedent(""" + import os + from test import support + with support.temp_cwd() as temp_path: + pid = os.fork() + if pid != 0: + # parent process (child has pid == 0) + + # wait for the child to terminate + (pid, status) = os.waitpid(pid, 0) + if status != 0: + raise AssertionError("Child process failed with exit " + "status indication " + "0x{:x}.".format(status)) + + # Make sure that temp_path is still present. When the child + # process leaves the 'temp_cwd'-context, the __exit__()- + # method of the context must not remove the temporary + # directory. + if not os.path.isdir(temp_path): + raise AssertionError("Child removed temp_path.") + """)) + # Tests for change_cwd() def test_change_cwd(self): diff --git a/Misc/ACKS b/Misc/ACKS index e02060d8dcf1bb..28b01e8cc7c5ad 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -774,6 +774,7 @@ Pedro Kroger Hannu Krosing Andrej Krpic Ivan Krstić +Anselm Kruis Steven Kryskalla Andrew Kuchling Dave Kuhlman
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: