Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-30028: make test.support.temp_cwd() fork-safe #1066

Merged
merged 8 commits into from
Feb 23, 2018

Conversation

akruis
Copy link

@akruis akruis commented Apr 9, 2017

Improve the context manager test.support.temp_cwd() to not remove the temporary
directory, if a forked child terminates.

https://bugs.python.org/issue30028

Improve the context manager test.support.temp_cwd() to not remove the temporary
directory, if a forked child terminates.
@mention-bot
Copy link

@akruis, thanks for your PR! By analyzing the history of the files in this pull request, we identified @serhiy-storchaka, @Yhg1s and @ncoghlan to be potential reviewers.

class TempCwdTestCase(unittest.TestCase):
@unittest.skipUnless(hasattr(os, "fork"), "test requires os.fork")
def test_forked_child(self):
import sys
Copy link
Member

Choose a reason for hiding this comment

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

Is it used?

Copy link
Author

Choose a reason for hiding this comment

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

Opps, a left over from a debug print to sys.stderr

Remove an unused "import sys".
try:
yield path
finally:
if dir_created:
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.

@@ -821,5 +821,19 @@ def test_crashed(self):
randomize=True)


class TempCwdTestCase(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

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

Please move this test to test_support.py which tests test.support.

test_regrtest tests Lib/test/libregrtest/.

Added an explanatory comment and moved the test to test_support.py.
I also modified the test to be in line with the other tests of temp_cwd.
@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."""
with support.temp_cwd() as 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.

Hum, please don't use fork in a test process. Write a short script run with test.support.script_helper. Otherwise, I expect too many issues like bad handling of KeyboardInterrupt. Use textwrap.dedent() to include the script directly here.

Copy link
Author

Choose a reason for hiding this comment

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

Done (1a0364d). Is the patch now OK?

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

An assert might removed depending on Python options.
@akruis
Copy link
Author

akruis commented Apr 17, 2017

@Haypo and @serhiy-storchaka: Any chance to get this PR merged?

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
if not os.path.isdir(temp_path):
raise AssertionError("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.

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?

@@ -161,6 +163,23 @@ 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.

- better comments
- make sure, that the child exits successfully
akruis pushed a commit to stackless-dev/stackless that referenced this pull request Sep 5, 2017
This commit merges the fix from C-Python pull request
python#1066 (git commit 22e032a) for
bpo-30028. Without this change
   $ ./python -m test.regrtest test_multiprocessing_fork
fails. ($ ./python -m test.test_multiprocessing_fork is OK.)

https://bitbucket.org/stackless-dev/stackless/issues/112
akruis pushed a commit to akruis/cpython that referenced this pull request Sep 9, 2017
This commit merges the fix from C-Python pull request
python#1066 (git commit 22e032a) for
bpo-30028. Without this change
   $ ./python -m test.regrtest test_multiprocessing_fork
fails. ($ ./python -m test.test_multiprocessing_fork is OK.)

https://bitbucket.org/stackless-dev/stackless/issues/112
(grafted from bda8a9d487da7cfbe4357d5c4c7635e0de19c6af)
@gpshead gpshead self-assigned this Jan 30, 2018
@brettcannon
Copy link
Member

To try and help move older pull requests forward, we are going through and backfilling 'awaiting' labels on pull requests that are lacking the label. Based on the current reviews, the best we can tell in an automated fashion is that a core developer requested changes to be made to this pull request.

If/when the requested changes have been made, please leave a comment that says, I have made the requested changes; please review again. That will trigger a bot to flag this pull request as ready for a follow-up review.

@serhiy-storchaka
Copy link
Member

I think requests by @vstinner were satisfied.

@serhiy-storchaka
Copy link
Member

A news entry is not required since this function is for internal use, but it would be worth to add your name @akruis into Misc/ACKS.

Proposed by Serhiy Storchaka.
@akruis
Copy link
Author

akruis commented Feb 22, 2018

Is there anything, I can do to get this PR merged?

@gpshead gpshead merged commit 33dddac into python:master Feb 23, 2018
@miss-islington
Copy link
Contributor

Thanks @akruis for the PR, and @gpshead for merging it 🌮🎉.. I'm working now to backport this PR to: 2.7, 3.6, 3.7.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Feb 23, 2018
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 33dddac)

Co-authored-by: Anselm Kruis <[email protected]>
@bedevere-bot
Copy link

GH-5824 is a backport of this pull request to the 3.7 branch.

@miss-islington
Copy link
Contributor

Sorry, @akruis and @gpshead, I could not cleanly backport this to 2.7 due to a conflict.
Please backport using cherry_picker on command line.
cherry_picker 33dddac00ba8d9b72cf21b8698504077eb3c23ad 2.7

@miss-islington
Copy link
Contributor

Sorry, @akruis and @gpshead, I could not cleanly backport this to 3.6 due to a conflict.
Please backport using cherry_picker on command line.
cherry_picker 33dddac00ba8d9b72cf21b8698504077eb3c23ad 3.6

@gpshead
Copy link
Member

gpshead commented Feb 23, 2018

I'm not sure it is actually worth backporting this to 3.6 or 2.7 for this internal test support library issue but if you want to do so, just create PRs using cherry_picker and tag me on them for review/merge. :)

miss-islington added a commit that referenced this pull request Feb 23, 2018
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 33dddac)

Co-authored-by: Anselm Kruis <[email protected]>
akruis pushed a commit to akruis/cpython that referenced this pull request Feb 23, 2018
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 33dddac)

Co-authored-by: Anselm Kruis <[email protected]>
@bedevere-bot
Copy link

GH-5825 is a backport of this pull request to the 2.7 branch.

akruis pushed a commit to akruis/cpython that referenced this pull request Feb 23, 2018
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 33dddac)

Co-authored-by: Anselm Kruis <[email protected]>
@bedevere-bot
Copy link

GH-5826 is a backport of this pull request to the 3.6 branch.

@akruis akruis deleted the tempcwd_fork_fix branch February 23, 2018 11:45
gpshead pushed a commit that referenced this pull request Feb 23, 2018
…-5825)

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 33dddac)

Co-authored-by: Anselm Kruis <[email protected]>
gpshead pushed a commit that referenced this pull request Feb 23, 2018
…-5826)

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 33dddac)

Co-authored-by: Anselm Kruis <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
skip news tests Tests in the Lib/test dir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants