Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -960,10 +960,14 @@ def temp_dir(path=None, quiet=False):
warnings.warn(f'tests may fail, unable to create '
f'temporary directory {path!r}: {exc}',
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():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test is non obvious, can you please add a short comment explaining why you test the pid?

I guess that it's test to avoid that two processes try to remove the directory if the parent uses fork()?

Add bpo-30028 in the comment.

rmtree(path)

@contextlib.contextmanager
Expand Down
18 changes: 18 additions & 0 deletions Lib/test/test_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import socket
import tempfile
import errno
import textwrap
from test import support
from test.support import script_helper

TESTFN = support.TESTFN

Expand Down Expand Up @@ -161,6 +163,22 @@ def test_temp_dir__existing_dir__quiet_true(self):
f'temporary directory {path!r}: '),
warn)

@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."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a reference to the issue: bpo-30028

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No other doc string in this file contains a reference to bpo. Therefore I added the reference as a comment.

# 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
os.waitpid(pid, 0) # wait for the child to terminate
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please test that the child didn't fail.

# make sure that temp_path is still present
assert os.path.isdir(temp_path), "Child removed temp_path."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid assert keyword which might be removed depending on the Python option, but use an explicit if + raise Exception(...). But maybe it's ok, I don't know :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is a subprocess, explicit os.exit() can be more appropriate.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm currently on a business trip and can't access my Linux box. I'll update the pull request on Thursday. But could you please agree on either raising AssertionError or a print() and explicit os.exit(). In the end it makes no difference.

"""))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment explaining that the child exits without removing the temporary directory.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the comment above enough?


# Tests for change_cwd()

def test_change_cwd(self):
Expand Down