[issue40826] PyOS_InterruptOccurred() now requires to hold the GIL: PyOS_Readline() crash
STINNER Victor
report at bugs.python.org
Mon Jun 1 11:23:52 EDT 2020
STINNER Victor <vstinner at python.org> added the comment:
It seems like this issue was introduced by this change:
commit 728189884e0e128c4ffc57b785b04584d57a90c0
Author: Victor Stinner <vstinner at python.org>
Date: Thu Mar 26 22:28:11 2020 +0100
bpo-38644: Pass tstate explicitly in signalmodule.c (GH-19184)
PyOS_InterruptOccurred() now checks _Py_ThreadCanHandleSignals()
before checking if SIGINT is tripped.
Include/internal/pycore_pyerrors.h | 2 +
Modules/signalmodule.c | 152 ++++++++++++++++++++++---------------
Python/ceval.c | 4 +-
3 files changed, 93 insertions(+), 65 deletions(-)
Before:
---
static inline int
_Py_IsMainInterpreter(PyThreadState* tstate)
{
/* Use directly _PyRuntime rather than tstate->interp->runtime, since
this function is used in performance critical code path (ceval) */
return (tstate->interp == _PyRuntime.interpreters.main);
}
static inline int
_Py_ThreadCanHandleSignals(PyThreadState *tstate)
{
return (_Py_IsMainThread() && _Py_IsMainInterpreter(tstate));
}
static int
thread_can_handle_signals(void)
{
PyThreadState *tstate = _PyThreadState_GET();
return _Py_ThreadCanHandleSignals(tstate);
}
int
PyOS_InterruptOccurred(void)
{
if (_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) {
if (!thread_can_handle_signals()) {
return 0;
}
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0);
return 1;
}
return 0;
}
---
After:
---
static inline int
_Py_IsMainInterpreter(PyThreadState* tstate)
{
/* Use directly _PyRuntime rather than tstate->interp->runtime, since
this function is used in performance critical code path (ceval) */
return (tstate->interp == _PyRuntime.interpreters.main);
}
static inline int
_Py_ThreadCanHandleSignals(PyThreadState *tstate)
{
return (_Py_IsMainThread() && _Py_IsMainInterpreter(tstate));
}
int
PyOS_InterruptOccurred(void)
{
PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) {
return 0;
}
if (!_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) {
return 0;
}
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0);
return 1;
}
---
The difference is that tstate->interp is now checked *before* checking if SIGINT signal is tripped.
----------
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue40826>
_______________________________________
More information about the Python-bugs-list
mailing list