Skip to content

Commit 67e8d41

Browse files
authored
gh-109693: Use pyatomic.h for signal module (gh-110480)
1 parent bdbe43c commit 67e8d41

File tree

3 files changed

+26
-27
lines changed

3 files changed

+26
-27
lines changed

Include/internal/pycore_signal.h

+7-9
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ extern "C" {
1010
# error "this header requires Py_BUILD_CORE define"
1111
#endif
1212

13-
#include "pycore_atomic.h" // _Py_atomic_address
1413
#include <signal.h> // NSIG
1514

1615

@@ -38,12 +37,10 @@ PyAPI_FUNC(void) _Py_RestoreSignals(void);
3837
#define INVALID_FD (-1)
3938

4039
struct _signals_runtime_state {
41-
volatile struct {
42-
_Py_atomic_int tripped;
43-
/* func is atomic to ensure that PyErr_SetInterrupt is async-signal-safe
44-
* (even though it would probably be otherwise, anyway).
45-
*/
46-
_Py_atomic_address func;
40+
struct {
41+
// tripped and func should be accessed using atomic ops.
42+
int tripped;
43+
PyObject* func;
4744
} handlers[Py_NSIG];
4845

4946
volatile struct {
@@ -63,8 +60,9 @@ struct _signals_runtime_state {
6360
#endif
6461
} wakeup;
6562

66-
/* Speed up sigcheck() when none tripped */
67-
_Py_atomic_int is_tripped;
63+
/* Speed up sigcheck() when none tripped.
64+
is_tripped should be accessed using atomic ops. */
65+
int is_tripped;
6866

6967
/* These objects necessarily belong to the main interpreter. */
7068
PyObject *default_handler;

Modules/signalmodule.c

+18-17
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
/* XXX Signals should be recorded per thread, now we have thread state. */
55

66
#include "Python.h"
7-
#include "pycore_atomic.h" // _Py_atomic_int
87
#include "pycore_call.h" // _PyObject_Call()
98
#include "pycore_ceval.h" // _PyEval_SignalReceived()
109
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
@@ -124,13 +123,15 @@ typedef struct {
124123
Py_LOCAL_INLINE(PyObject *)
125124
get_handler(int i)
126125
{
127-
return (PyObject *)_Py_atomic_load(&Handlers[i].func);
126+
return (PyObject *)_Py_atomic_load_ptr(&Handlers[i].func);
128127
}
129128

130129
Py_LOCAL_INLINE(void)
131130
set_handler(int i, PyObject* func)
132131
{
133-
_Py_atomic_store(&Handlers[i].func, (uintptr_t)func);
132+
/* Store func with atomic operation to ensure
133+
that PyErr_SetInterrupt is async-signal-safe. */
134+
_Py_atomic_store_ptr(&Handlers[i].func, func);
134135
}
135136

136137

@@ -267,11 +268,11 @@ report_wakeup_send_error(void* data)
267268
static void
268269
trip_signal(int sig_num)
269270
{
270-
_Py_atomic_store_relaxed(&Handlers[sig_num].tripped, 1);
271+
_Py_atomic_store_int(&Handlers[sig_num].tripped, 1);
271272

272273
/* Set is_tripped after setting .tripped, as it gets
273274
cleared in PyErr_CheckSignals() before .tripped. */
274-
_Py_atomic_store(&is_tripped, 1);
275+
_Py_atomic_store_int(&is_tripped, 1);
275276

276277
/* Signals are always handled by the main interpreter */
277278
PyInterpreterState *interp = _PyInterpreterState_Main();
@@ -1731,7 +1732,7 @@ _PySignal_Fini(void)
17311732
// Restore default signals and clear handlers
17321733
for (int signum = 1; signum < Py_NSIG; signum++) {
17331734
PyObject *func = get_handler(signum);
1734-
_Py_atomic_store_relaxed(&Handlers[signum].tripped, 0);
1735+
_Py_atomic_store_int_relaxed(&Handlers[signum].tripped, 0);
17351736
set_handler(signum, NULL);
17361737
if (func != NULL
17371738
&& func != Py_None
@@ -1785,7 +1786,7 @@ int
17851786
_PyErr_CheckSignalsTstate(PyThreadState *tstate)
17861787
{
17871788
_Py_CHECK_EMSCRIPTEN_SIGNALS();
1788-
if (!_Py_atomic_load(&is_tripped)) {
1789+
if (!_Py_atomic_load_int(&is_tripped)) {
17891790
return 0;
17901791
}
17911792

@@ -1803,15 +1804,15 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
18031804
* we receive a signal i after we zero is_tripped and before we
18041805
* check Handlers[i].tripped.
18051806
*/
1806-
_Py_atomic_store(&is_tripped, 0);
1807+
_Py_atomic_store_int(&is_tripped, 0);
18071808

18081809
_PyInterpreterFrame *frame = _PyThreadState_GetFrame(tstate);
18091810
signal_state_t *state = &signal_global_state;
18101811
for (int i = 1; i < Py_NSIG; i++) {
1811-
if (!_Py_atomic_load_relaxed(&Handlers[i].tripped)) {
1812+
if (!_Py_atomic_load_int_relaxed(&Handlers[i].tripped)) {
18121813
continue;
18131814
}
1814-
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
1815+
_Py_atomic_store_int_relaxed(&Handlers[i].tripped, 0);
18151816

18161817
/* Signal handlers can be modified while a signal is received,
18171818
* and therefore the fact that trip_signal() or PyErr_SetInterrupt()
@@ -1857,7 +1858,7 @@ _PyErr_CheckSignalsTstate(PyThreadState *tstate)
18571858
}
18581859
if (!result) {
18591860
/* On error, re-schedule a call to _PyErr_CheckSignalsTstate() */
1860-
_Py_atomic_store(&is_tripped, 1);
1861+
_Py_atomic_store_int(&is_tripped, 1);
18611862
return -1;
18621863
}
18631864

@@ -1975,7 +1976,7 @@ _PySignal_Init(int install_signal_handlers)
19751976
#endif
19761977

19771978
for (int signum = 1; signum < Py_NSIG; signum++) {
1978-
_Py_atomic_store_relaxed(&Handlers[signum].tripped, 0);
1979+
_Py_atomic_store_int_relaxed(&Handlers[signum].tripped, 0);
19791980
}
19801981

19811982
if (install_signal_handlers) {
@@ -1997,11 +1998,11 @@ _PyOS_InterruptOccurred(PyThreadState *tstate)
19971998
return 0;
19981999
}
19992000

2000-
if (!_Py_atomic_load_relaxed(&Handlers[SIGINT].tripped)) {
2001+
if (!_Py_atomic_load_int_relaxed(&Handlers[SIGINT].tripped)) {
20012002
return 0;
20022003
}
20032004

2004-
_Py_atomic_store_relaxed(&Handlers[SIGINT].tripped, 0);
2005+
_Py_atomic_store_int_relaxed(&Handlers[SIGINT].tripped, 0);
20052006
return 1;
20062007
}
20072008

@@ -2019,13 +2020,13 @@ PyOS_InterruptOccurred(void)
20192020
static void
20202021
_clear_pending_signals(void)
20212022
{
2022-
if (!_Py_atomic_load(&is_tripped)) {
2023+
if (!_Py_atomic_load_int(&is_tripped)) {
20232024
return;
20242025
}
20252026

2026-
_Py_atomic_store(&is_tripped, 0);
2027+
_Py_atomic_store_int(&is_tripped, 0);
20272028
for (int i = 1; i < Py_NSIG; ++i) {
2028-
_Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
2029+
_Py_atomic_store_int_relaxed(&Handlers[i].tripped, 0);
20292030
}
20302031
}
20312032

Python/ceval_gil.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ update_eval_breaker_from_thread(PyInterpreterState *interp, PyThreadState *tstat
7676
_Py_set_eval_breaker_bit(interp, _PY_CALLS_TO_DO_BIT, 1);
7777
}
7878
if (_Py_ThreadCanHandleSignals(interp)) {
79-
if (_Py_atomic_load(&_PyRuntime.signals.is_tripped)) {
79+
if (_Py_atomic_load_int(&_PyRuntime.signals.is_tripped)) {
8080
_Py_set_eval_breaker_bit(interp, _PY_SIGNALS_PENDING_BIT, 1);
8181
}
8282
}

0 commit comments

Comments
 (0)