Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ extern void _Py_FinishPendingCalls(PyThreadState *tstate);
extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
extern int _PyEval_InitState(struct _ceval_state *ceval);
extern void _PyEval_FiniState(struct _ceval_state *ceval);
PyAPI_FUNC(void) _PyEval_SignalReceived(PyThreadState *tstate);
PyAPI_FUNC(void) _PyEval_SignalReceived(PyInterpreterState *interp);
PyAPI_FUNC(int) _PyEval_AddPendingCall(
PyThreadState *tstate,
PyInterpreterState *interp,
int (*func)(void *),
void *arg);
PyAPI_FUNC(void) _PyEval_SignalAsyncExc(PyThreadState *tstate);
Expand Down
13 changes: 9 additions & 4 deletions Include/internal/pycore_pystate.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,9 @@ _Py_IsMainInterpreter(PyThreadState* tstate)

/* Only handle signals on the main thread of the main interpreter. */
static inline int
_Py_ThreadCanHandleSignals(PyThreadState *tstate)
_Py_ThreadCanHandleSignals(PyInterpreterState *interp)
{
return (_Py_IsMainThread() && _Py_IsMainInterpreter(tstate));
return (_Py_IsMainThread() && interp == _PyRuntime.interpreters.main);
}


Expand Down Expand Up @@ -340,7 +340,9 @@ static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *run
The caller must hold the GIL.

See also PyThreadState_Get() and PyThreadState_GET(). */
#define _PyThreadState_GET() _PyRuntimeState_GetThreadState(&_PyRuntime)
static inline PyThreadState *_PyThreadState_GET(void) {
return _PyRuntimeState_GetThreadState(&_PyRuntime);
}

/* Redefine PyThreadState_GET() as an alias to _PyThreadState_GET() */
#undef PyThreadState_GET
Expand All @@ -354,7 +356,10 @@ static inline PyThreadState* _PyRuntimeState_GetThreadState(_PyRuntimeState *run

See also _PyInterpreterState_Get()
and _PyGILState_GetInterpreterStateUnsafe(). */
#define _PyInterpreterState_GET_UNSAFE() (_PyThreadState_GET()->interp)
static inline PyInterpreterState* _PyInterpreterState_GET_UNSAFE(void) {
PyThreadState *tstate = _PyThreadState_GET();
return tstate->interp;
}


/* Other */
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix the signal handler: it now always uses the main interpreter, rather than
trying to get the current Python thread state.
27 changes: 12 additions & 15 deletions Modules/signalmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,14 +252,11 @@ trip_signal(int sig_num)
cleared in PyErr_CheckSignals() before .tripped. */
_Py_atomic_store(&is_tripped, 1);

/* Get the Python thread state using PyGILState API, since
_PyThreadState_GET() returns NULL if the GIL is released.
For example, signal.raise_signal() releases the GIL. */
PyThreadState *tstate = PyGILState_GetThisThreadState();
assert(tstate != NULL);
/* Signals are always handled by the main interpreter */
PyInterpreterState *interp = _PyRuntime.interpreters.main;

/* Notify ceval.c */
_PyEval_SignalReceived(tstate);
_PyEval_SignalReceived(interp);

/* And then write to the wakeup fd *after* setting all the globals and
doing the _PyEval_SignalReceived. We used to write to the wakeup fd
Expand Down Expand Up @@ -299,7 +296,7 @@ trip_signal(int sig_num)
{
/* _PyEval_AddPendingCall() isn't signal-safe, but we
still use it for this exceptional case. */
_PyEval_AddPendingCall(tstate,
_PyEval_AddPendingCall(interp,
report_wakeup_send_error,
(void *)(intptr_t) last_error);
}
Expand All @@ -318,7 +315,7 @@ trip_signal(int sig_num)
{
/* _PyEval_AddPendingCall() isn't signal-safe, but we
still use it for this exceptional case. */
_PyEval_AddPendingCall(tstate,
_PyEval_AddPendingCall(interp,
report_wakeup_write_error,
(void *)(intptr_t)errno);
}
Expand Down Expand Up @@ -476,7 +473,7 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
#endif

PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) {
if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
_PyErr_SetString(tstate, PyExc_ValueError,
"signal only works in main thread "
"of the main interpreter");
Expand Down Expand Up @@ -704,7 +701,7 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args, PyObject *kwds)
#endif

PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) {
if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
_PyErr_SetString(tstate, PyExc_ValueError,
"set_wakeup_fd only works in main thread "
"of the main interpreter");
Expand Down Expand Up @@ -1681,7 +1678,7 @@ int
PyErr_CheckSignals(void)
{
PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) {
if (!_Py_ThreadCanHandleSignals(tstate->interp)) {
return 0;
}

Expand Down Expand Up @@ -1787,8 +1784,8 @@ PyOS_FiniInterrupts(void)
int
PyOS_InterruptOccurred(void)
{
PyThreadState *tstate = _PyThreadState_GET();
if (!_Py_ThreadCanHandleSignals(tstate)) {
PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
if (!_Py_ThreadCanHandleSignals(interp)) {
return 0;
}

Expand Down Expand Up @@ -1824,8 +1821,8 @@ _PySignal_AfterFork(void)
int
_PyOS_IsMainThread(void)
{
PyThreadState *tstate = _PyThreadState_GET();
return _Py_ThreadCanHandleSignals(tstate);
PyInterpreterState *interp = _PyInterpreterState_GET_UNSAFE();
return _Py_ThreadCanHandleSignals(interp);
}

#ifdef MS_WINDOWS
Expand Down
Loading