[3.6] bpo-30808: Use _Py_atomic API for concurrency-sensitive signal state (GH-2417) by pitrou · Pull Request #3007 · python/cpython
static volatile struct { sig_atomic_t tripped; _Py_atomic_int tripped; PyObject *func; } Handlers[NSIG];
/* Speed up sigcheck() when none tripped */ static volatile sig_atomic_t is_tripped = 0; static _Py_atomic_int is_tripped;
static PyObject *DefaultHandler; static PyObject *IgnoreHandler;
Handlers[sig_num].tripped = 1; _Py_atomic_store_relaxed(&Handlers[sig_num].tripped, 1);
/* Set is_tripped after setting .tripped, as it gets cleared in PyErr_CheckSignals() before .tripped. */ is_tripped = 1; _Py_atomic_store(&is_tripped, 1);
/* Notify ceval.c */ _PyEval_SignalReceived();
/* And then write to the wakeup fd *after* setting all the globals and
Handlers[0].tripped = 0; _Py_atomic_store_relaxed(&Handlers[0].tripped, 0); for (i = 1; i < NSIG; i++) { void (*t)(int); t = PyOS_getsig(i); Handlers[i].tripped = 0; _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); if (t == SIG_DFL) Handlers[i].func = DefaultHandler; else if (t == SIG_IGN)
for (i = 1; i < NSIG; i++) { func = Handlers[i].func; Handlers[i].tripped = 0; _Py_atomic_store_relaxed(&Handlers[i].tripped, 0); Handlers[i].func = NULL; if (i != SIGINT && func != NULL && func != Py_None && func != DefaultHandler && func != IgnoreHandler)
if (!is_tripped) if (!_Py_atomic_load(&is_tripped)) return 0;
#ifdef WITH_THREAD
if (!(f = (PyObject *)PyEval_GetFrame())) f = Py_None;
for (i = 1; i < NSIG; i++) { if (Handlers[i].tripped) { if (_Py_atomic_load_relaxed(&Handlers[i].tripped)) { PyObject *result = NULL; PyObject *arglist = Py_BuildValue("(iO)", i, f); Handlers[i].tripped = 0; _Py_atomic_store_relaxed(&Handlers[i].tripped, 0);
if (arglist) { result = PyEval_CallObject(Handlers[i].func, arglist); Py_DECREF(arglist); } if (!result) { is_tripped = 1; _Py_atomic_store(&is_tripped, 1); return -1; }