Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
[WIP] bpo-30703: More reentrant signal handler#2408
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
Uh oh!
There was an error while loading. Please reload this page.
Conversation
Modify the signal handler to not call Py_AddPendingCall() function since this function uses a lock and a list, and so is unlikely to be reentrant. Add a new _PyEval_SignalReceived() function which only writes into an atomic variable and so is reentrant.
| { | ||
| /* bpo-30703: Function called when the C signal handler of Python gets a | ||
| signal. We cannot queue a callback using Py_AddPendingCall() since this | ||
| function is not reentrant (use a lock and a list). */ |
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.
s/use/uses/
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.
Also say "signal-safe" rather than "reentrant", since otherwise it's not clear how Py_AddPendingCall can be called reentrantly.
| int r = 0; | ||
| /* Python signal handler doesn't really queue a callback: it only signals | ||
| that an UNIX signal was received, see _PyEval_SignalReceived(). */ |
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.
You can remove "UNIX", as even Windows has a couple of signals :-)
pitrou commented Jun 26, 2017
What about the part without WITH_THREAD? :-) |
| /* Python signal handler doesn't really queue a callback: it only signals | ||
| that an UNIX signal was received, see _PyEval_SignalReceived(). */ | ||
| if (PyErr_CheckSignals() < 0){ |
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.
Perhaps this should be called after the check for main_thread and busy?
pitrou commented Jun 26, 2017
Ok, I think there is a problem with this patch. What if a C signal is received just after |
pitrou commented Jun 26, 2017
This is why, by the way, |
pitrou commented Jun 26, 2017
A possible solution should be to call UNSIGNAL_PENDING_CALLS() before calling PyErr_CheckSignals(), and remove the UNSIGNAL_PENDING_CALLS() call from the Py_MakePendingCalls() loop. Also, perhaps change the bit that calls Py_MakePendingCalls() in the eval loop to: (i.e. change the |
pitrou commented Jun 26, 2017
It's difficult to reproduce the race condition described above but here is a script that may work: |
pitrou commented Jun 26, 2017
This patch applied to your PR should make things better: |
vstinner commented Jun 26, 2017
Please push directly into my branch, you are allowed to do that ;-) See maybe https://docs.python.org/devguide/gitbootcamp.html#editing-a-pull-request-prior-to-merging |
vstinner commented Jun 26, 2017
I added [WIP] to the title, since I didn't test my change. I was more to discuss a practical solution to the problem. It seems like you spotted bugs in my implementation, thanks ;-) |
pitrou commented Jun 26, 2017
That doesn't work. I get: |
pitrou commented Jun 26, 2017
I'll create another PR instead of dealing with git cruft. |
pitrou commented Jun 26, 2017
See #2415 |
vstinner commented Jun 26, 2017
It seems like you used the HTTPS URL. I suggest you to use the SSH URL. Moreover, when I try to push to a different repository, I try to only push a single branch. For example, to push the to BRANCH branch of REMOTE remote, you can type: HEAD uses the current branch, ":BRANCH" means that you push to REMOTE:BRANCH. Non obvious syntax, but I like it. |
pitrou commented Jun 26, 2017
It is what I tried before (see above) :-)
I'm almost sure I'll have forgotten that the next time I'll need it :-/ |
Modify the signal handler to not call Py_AddPendingCall() function
since this function uses a lock and a list, and so is unlikely to be
reentrant. Add a new _PyEval_SignalReceived() function which only
writes into an atomic variable and so is reentrant.