gh-109693: Use pyatomic.h for signal module (gh-110480)

This commit is contained in:
Donghee Na 2023-10-10 08:26:29 +09:00 committed by GitHub
parent bdbe43c7d0
commit 67e8d416cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 27 deletions

View File

@ -10,7 +10,6 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define" # error "this header requires Py_BUILD_CORE define"
#endif #endif
#include "pycore_atomic.h" // _Py_atomic_address
#include <signal.h> // NSIG #include <signal.h> // NSIG
@ -38,12 +37,10 @@ PyAPI_FUNC(void) _Py_RestoreSignals(void);
#define INVALID_FD (-1) #define INVALID_FD (-1)
struct _signals_runtime_state { struct _signals_runtime_state {
volatile struct { struct {
_Py_atomic_int tripped; // tripped and func should be accessed using atomic ops.
/* func is atomic to ensure that PyErr_SetInterrupt is async-signal-safe int tripped;
* (even though it would probably be otherwise, anyway). PyObject* func;
*/
_Py_atomic_address func;
} handlers[Py_NSIG]; } handlers[Py_NSIG];
volatile struct { volatile struct {
@ -63,8 +60,9 @@ struct _signals_runtime_state {
#endif #endif
} wakeup; } wakeup;
/* Speed up sigcheck() when none tripped */ /* Speed up sigcheck() when none tripped.
_Py_atomic_int is_tripped; is_tripped should be accessed using atomic ops. */
int is_tripped;
/* These objects necessarily belong to the main interpreter. */ /* These objects necessarily belong to the main interpreter. */
PyObject *default_handler; PyObject *default_handler;

View File

@ -4,7 +4,6 @@
/* XXX Signals should be recorded per thread, now we have thread state. */ /* XXX Signals should be recorded per thread, now we have thread state. */
#include "Python.h" #include "Python.h"
#include "pycore_atomic.h" // _Py_atomic_int
#include "pycore_call.h" // _PyObject_Call() #include "pycore_call.h" // _PyObject_Call()
#include "pycore_ceval.h" // _PyEval_SignalReceived() #include "pycore_ceval.h" // _PyEval_SignalReceived()
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS #include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
@ -124,13 +123,15 @@ typedef struct {
Py_LOCAL_INLINE(PyObject *) Py_LOCAL_INLINE(PyObject *)
get_handler(int i) get_handler(int i)
{ {
return (PyObject *)_Py_atomic_load(&Handlers[i].func); return (PyObject *)_Py_atomic_load_ptr(&Handlers[i].func);
} }
Py_LOCAL_INLINE(void) Py_LOCAL_INLINE(void)
set_handler(int i, PyObject* func) set_handler(int i, PyObject* func)
{ {
_Py_atomic_store(&Handlers[i].func, (uintptr_t)func); /* Store func with atomic operation to ensure
that PyErr_SetInterrupt is async-signal-safe. */
_Py_atomic_store_ptr(&Handlers[i].func, func);
} }
@ -267,11 +268,11 @@ report_wakeup_send_error(void* data)
static void static void
trip_signal(int sig_num) trip_signal(int sig_num)
{ {
_Py_atomic_store_relaxed(&Handlers[sig_num].tripped, 1); _Py_atomic_store_int(&Handlers[sig_num].tripped, 1);
/* Set is_tripped after setting .tripped, as it gets /* Set is_tripped after setting .tripped, as it gets
cleared in PyErr_CheckSignals() before .tripped. */ cleared in PyErr_CheckSignals() before .tripped. */
_Py_atomic_store(&is_tripped, 1); _Py_atomic_store_int(&is_tripped, 1);
/* Signals are always handled by the main interpreter */ /* Signals are always handled by the main interpreter */
PyInterpreterState *interp = _PyInterpreterState_Main(); PyInterpreterState *interp = _PyInterpreterState_Main();
@ -1731,7 +1732,7 @@ _PySignal_Fini(void)
// Restore default signals and clear handlers // Restore default signals and clear handlers
for (int signum = 1; signum < Py_NSIG; signum++) { for (int signum = 1; signum < Py_NSIG; signum++) {
PyObject *func = get_handler(signum); PyObject *func = get_handler(signum);
_Py_atomic_store_relaxed(&Handlers[signum].tripped, 0); _Py_atomic_store_int_relaxed(&Handlers[signum].tripped, 0);
set_handler(signum, NULL); set_handler(signum, NULL);
if (func != NULL if (func != NULL
&& func != Py_None && func != Py_None
@ -1785,7 +1786,7 @@ int
_PyErr_CheckSignalsTstate(PyThreadState *tstate) _PyErr_CheckSignalsTstate(PyThreadState *tstate)
{ {
_Py_CHECK_EMSCRIPTEN_SIGNALS(); _Py_CHECK_EMSCRIPTEN_SIGNALS();
if (!_Py_atomic_load(&is_tripped)) { if (!_Py_atomic_load_int(&is_tripped)) {
return 0; return 0;
} }
@ -1803,15 +1804,15 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
* we receive a signal i after we zero is_tripped and before we * we receive a signal i after we zero is_tripped and before we
* check Handlers[i].tripped. * check Handlers[i].tripped.
*/ */
_Py_atomic_store(&is_tripped, 0); _Py_atomic_store_int(&is_tripped, 0);
_PyInterpreterFrame *frame = _PyThreadState_GetFrame(tstate); _PyInterpreterFrame *frame = _PyThreadState_GetFrame(tstate);
signal_state_t *state = &signal_global_state; signal_state_t *state = &signal_global_state;
for (int i = 1; i < Py_NSIG; i++) { for (int i = 1; i < Py_NSIG; i++) {
if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) { if (!_Py_atomic_load_int_relaxed(&Handlers[i].tripped)) {
continue; continue;
} }
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0); _Py_atomic_store_int_relaxed(&Handlers[i].tripped, 0);
/* Signal handlers can be modified while a signal is received, /* Signal handlers can be modified while a signal is received,
* and therefore the fact that trip_signal() or PyErr_SetInterrupt() * and therefore the fact that trip_signal() or PyErr_SetInterrupt()
@ -1857,7 +1858,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
} }
if (!result) { if (!result) {
/* On error, re-schedule a call to _PyErr_CheckSignalsTstate() */ /* On error, re-schedule a call to _PyErr_CheckSignalsTstate() */
_Py_atomic_store(&is_tripped, 1); _Py_atomic_store_int(&is_tripped, 1);
return -1; return -1;
} }
@ -1975,7 +1976,7 @@ _PySignal_Init(int install_signal_handlers)
#endif #endif
for (int signum = 1; signum < Py_NSIG; signum++) { for (int signum = 1; signum < Py_NSIG; signum++) {
_Py_atomic_store_relaxed(&Handlers[signum].tripped, 0); _Py_atomic_store_int_relaxed(&Handlers[signum].tripped, 0);
} }
if (install_signal_handlers) { if (install_signal_handlers) {
@ -1997,11 +1998,11 @@ _PyOS_InterruptOccurred(PyThreadState *tstate)
return 0; return 0;
} }
if (!_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) { if (!_Py_atomic_load_int_relaxed(&Handlers[SIGINT].tripped)) {
return 0; return 0;
} }
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0); _Py_atomic_store_int_relaxed(&Handlers[SIGINT].tripped, 0);
return 1; return 1;
} }
@ -2019,13 +2020,13 @@ PyOS_InterruptOccurred(void)
static void static void
_clear_pending_signals(void) _clear_pending_signals(void)
{ {
if (!_Py_atomic_load(&is_tripped)) { if (!_Py_atomic_load_int(&is_tripped)) {
return; return;
} }
_Py_atomic_store(&is_tripped, 0); _Py_atomic_store_int(&is_tripped, 0);
for (int i = 1; i < Py_NSIG; ++i) { for (int i = 1; i < Py_NSIG; ++i) {
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0); _Py_atomic_store_int_relaxed(&Handlers[i].tripped, 0);
} }
} }

View File

@ -76,7 +76,7 @@ update_eval_breaker_from_thread(PyInterpreterState *interp, PyThreadState *tstat
_Py_set_eval_breaker_bit(interp, _PY_CALLS_TO_DO_BIT, 1); _Py_set_eval_breaker_bit(interp, _PY_CALLS_TO_DO_BIT, 1);
} }
if (_Py_ThreadCanHandleSignals(interp)) { if (_Py_ThreadCanHandleSignals(interp)) {
if (_Py_atomic_load(&_PyRuntime.signals.is_tripped)) { if (_Py_atomic_load_int(&_PyRuntime.signals.is_tripped)) {
_Py_set_eval_breaker_bit(interp, _PY_SIGNALS_PENDING_BIT, 1); _Py_set_eval_breaker_bit(interp, _PY_SIGNALS_PENDING_BIT, 1);
} }
} }