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-38630: subprocess: enhance send_signal() on Unix #16984

Merged
merged 1 commit into from Jan 15, 2020

Conversation

@vstinner
Copy link
Member

vstinner commented Oct 29, 2019

On Unix, subprocess.Popen.send_signal() now polls the process status.
Polling reduces the risk of sending a signal to the wrong process if
the process completed, but its identifier has been reassigned
(recycled) to a new different process.

https://bugs.python.org/issue38630

@vstinner

This comment has been minimized.

Copy link
Member Author

vstinner commented Oct 29, 2019

For the test, I tried to call os.kill(pid, 0) in a loop to wait until the process completes without calling waitpid(). os.kill(pid, 0) doesn't fail even if the process already completes. It only starts failing when waitpid() is called.

@vstinner

This comment has been minimized.

Copy link
Member Author

vstinner commented Oct 30, 2019

@gpshead: Would you mind to review this change? The additional poll() call should be cheap in term of performance and it makes the code "more correct" (reduce the risk of race condition).

@gpshead

This comment has been minimized.

Copy link
Member

gpshead commented Oct 30, 2019

feel free to backport this to 3.8 if you want.

@vstinner

This comment has been minimized.

Copy link
Member Author

vstinner commented Nov 5, 2019

Note for myself: I would like to elaborate a few comments before merging the change. I need to clarify in which cases the polling is required.

@vstinner vstinner force-pushed the vstinner:subprocess_send_signal branch 3 times, most recently from b6d1fa9 to de28363 Nov 5, 2019
@vstinner

This comment has been minimized.

Copy link
Member Author

vstinner commented Nov 5, 2019

@gpshead: I elaborated send_signal() comment. Would you mind to review my updated PR? I also added a comment explaining why my change does not fully fix the race condition, it only reduces the risk.

I would like to backport this bugfix to Python 3.7 and 3.8 branch.


By the way, what do you have think of modifying send_signal(), terminate() and kill() return value? Return True if a signal has been set, or False if the method did nothing.

The return value must not be modified in micro releases (3.7 and 3.8 branches). I'm only talking about the master branch (future Python 3.9).

I will propose a separated PR once this one is merged.

@vstinner vstinner requested a review from gpshead Nov 5, 2019
@vstinner

This comment has been minimized.

Copy link
Member Author

vstinner commented Nov 5, 2019

On Unix, subprocess.Popen.send_signal() now polls the process status.
Polling reduces the risk of sending a signal to the wrong process if
the process completed, the Popen.returncode attribute is still None,
and the pid has been reassigned (recycled) to a new different
process.
@vstinner vstinner force-pushed the vstinner:subprocess_send_signal branch from de28363 to 7fd2c75 Nov 5, 2019
@gpshead
gpshead approved these changes Nov 5, 2019
@gpshead

This comment has been minimized.

Copy link
Member

gpshead commented Nov 5, 2019

seems fine for 3.7 and 3.8 as well. i waffled on trying to enhance the wording in the docs to mention the possible race condition, but those are all unusual circumstances not worth laying out in the docs for send_signal.

@vstinner

This comment has been minimized.

Copy link
Member Author

vstinner commented Nov 6, 2019

i waffled on trying to enhance the wording in the docs to mention the possible race condition, but those are all unusual circumstances not worth laying out in the docs for send_signal.

I agree :-)

@vstinner

This comment has been minimized.

Copy link
Member Author

vstinner commented Nov 12, 2019

@giampaolo, @njsmith: I understand that there are other approaches to fix https://bugs.python.org/issue38630 but are you ok with this change which is simple enough and reduce the risk?

@njsmith

This comment has been minimized.

Copy link
Contributor

njsmith commented Nov 13, 2019

It's not clear to me that this actually does reduce the risk. Merging won't do any harm; it's a no-op at worst. But the comment seems misleading, and you should make sure the bug isn't marked as closed.

@giampaolo

This comment has been minimized.

Copy link
Contributor

giampaolo commented Nov 13, 2019

I don't have a strong opinion about this change. It seems it does not do any harm so it can probably be committed, but at the same time it does not solve the original problem either. For that (avoiding to kill() a reused process PID) the right solution IMO is using the process creation time. It appears to be more portable than using the pidfd API(s) as it's Linux only (?).

@njsmith

This comment has been minimized.

Copy link
Contributor

njsmith commented Nov 13, 2019

I don't see any way process creation time can fix the race condition (kill doesn't take a process creation time!), but that discussion should probably go in the bpo issue. That issue also has another suggestion that I think does actually solve the race condition.

@csabella

This comment has been minimized.

Copy link
Contributor

csabella commented Jan 11, 2020

Should this be flagged for additional discussion or is it ready to be merged? Thanks!

@vstinner vstinner merged commit e85a305 into python:master Jan 15, 2020
4 checks passed
4 checks passed
Azure Pipelines PR #20191105.34 succeeded
Details
bedevere/issue-number Issue number 38630 found
Details
bedevere/news News entry found in Misc/NEWS.d
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@vstinner vstinner deleted the vstinner:subprocess_send_signal branch Jan 15, 2020
petdance added a commit to petdance/cpython that referenced this pull request Jan 17, 2020
…H-16984)

On Unix, subprocess.Popen.send_signal() now polls the process status.
Polling reduces the risk of sending a signal to the wrong process if
the process completed, the Popen.returncode attribute is still None,
and the pid has been reassigned (recycled) to a new different
process.
petdance added a commit to petdance/cpython that referenced this pull request Jan 17, 2020
…H-16984)

On Unix, subprocess.Popen.send_signal() now polls the process status.
Polling reduces the risk of sending a signal to the wrong process if
the process completed, the Popen.returncode attribute is still None,
and the pid has been reassigned (recycled) to a new different
process.
petdance added a commit to petdance/cpython that referenced this pull request Jan 17, 2020
…H-16984)

On Unix, subprocess.Popen.send_signal() now polls the process status.
Polling reduces the risk of sending a signal to the wrong process if
the process completed, the Popen.returncode attribute is still None,
and the pid has been reassigned (recycled) to a new different
process.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants
You can’t perform that action at this time.