From 95ec069e5259be25619eb2a159808b6c7b5b8da7 Mon Sep 17 00:00:00 2001 From: Anselm Kruis Date: Fri, 23 Feb 2018 02:37:38 +0100 Subject: [PATCH] [2.7] bpo-30028: make test.support.temp_cwd() fork-safe (GH-1066) Make test.support.temp_cwd() fork-safe. The context manager test.support.temp_cwd() no longer removes the temporary directory when executing in a process other than the parent it entered from. If a forked child exits the context manager it won't do the cleanup.. (cherry picked from commit 33dddac00ba8d9b72cf21b8698504077eb3c23ad) Co-authored-by: Anselm Kruis --- Lib/test/support/__init__.py | 6 +++++- Lib/test/test_test_support.py | 30 ++++++++++++++++++++++++++++++ Misc/ACKS | 1 + 3 files changed, 36 insertions(+), 1 deletion(-) 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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

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:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy