-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
gh-128130: Fix unhandled keyboard interrupt data race #129975
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
Merged
colesbury
merged 1 commit into
python:main
from
colesbury:gh-128130-unhandled_keyboard_interrupt
Feb 13, 2025
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this being removed from the _PyErr_Display code paths? It was added by @pablogsal 's #110702 work & @iritkatriel 's review.
While we're sadly lacking comments in the code as to why... I believe this was for the scenario where we're heading back into Python code within the traceback printing and could thus receive a KeyboardInterrupt during that which we either wind up swallowing (bad - the "multiple Ctrl-C required to trigger the handler raising from a point the KeyboardInterrupt exception can propagate upwards to interrupt actual execution" problem that Python has had at times in the past? OR that none of the python code in the traceback printing path can swallow the KeyboardInterrupt state and prevent an ultimate exit_sigint() from terminating the process? (did I just describe the same thing twice?)
I'd be conservative and leave these here in
_PyErr_Display
, just using its now required atomic read and stores. It shouldn't be a speed-path, we're already rendering big strings and sending them out some file handle.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I'm generally sympathetic to being conservative when making changes, the
unhandled_keyboard_interrupt
logic can't be fixed by using atomic reads and writes. The saving and restoration done here could still end up erroneously clearing it in a different thread (even in the GIL-enabled build).It also is not useful here anymore. We previously cleared
unhandled_keyboard_interrupt
inrun_eval_code_obj
, which is called from many places, including_PyErr_Display
potentially. Now we are clearing it inPy_RunMain
, which is the same place we read it.The most important thing I'd like to convince you of is that we should be handling
KeyboardInterrupt
the same way asSystemError
. They are both exceptions that when unhandled should lead to Python exiting with specific error code and/or behavior.That's true before and after this PR -- the code did not handle that case. See this demo, for example: https://gist.github.com/colesbury/6871cc3d412c5d4fc51c7fd70e33e8a2
I think we should better handle that case, but probably not as part of this PR. This PR largely keeps the same behavior and handles the same cases as before, but avoids the race conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation! This code is one of those places that I go "eew" every time I dive in on it; challenging to reason about and hard to craft reliable specific regression tests for.
I like the after state of this change better. Definitely cleaner to keep the clearing and use in one place.