Skip to content

Commit

Permalink
signalmodule: fix thread-safety issue on macOS
Browse files Browse the repository at this point in the history
The sigaction function is not safe to call concurrently with raise()
on macOS.
  • Loading branch information
colesbury committed Apr 23, 2023
1 parent ada9b73 commit 0e0b389
Showing 1 changed file with 12 additions and 1 deletion.
13 changes: 12 additions & 1 deletion Modules/signalmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ typedef struct {
PyTypeObject *siginfo_type;
} _signal_module_state;

static _PyMutex signal_mutex;

Py_LOCAL_INLINE(PyObject *)
get_handler(int i)
Expand Down Expand Up @@ -437,9 +438,11 @@ signal_raise_signal_impl(PyObject *module, int signalnum)
{
int err;
Py_BEGIN_ALLOW_THREADS
_PyMutex_lock(&signal_mutex);
_Py_BEGIN_SUPPRESS_IPH
err = raise(signalnum);
_Py_END_SUPPRESS_IPH
_PyMutex_unlock(&signal_mutex);
Py_END_ALLOW_THREADS

if (err) {
Expand Down Expand Up @@ -479,6 +482,7 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
_signal_module_state *modstate = get_signal_state(module);
PyObject *old_handler;
void (*func)(int);
PyOS_sighandler_t e;
#ifdef MS_WINDOWS
/* Validate that signalnum is one of the allowable signals */
switch (signalnum) {
Expand Down Expand Up @@ -528,7 +532,14 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
if (_PyErr_CheckSignalsTstate(tstate)) {
return NULL;
}
if (PyOS_setsig(signalnum, func) == SIG_ERR) {

// On macOS, sigaction isn't thread-safe with concurrent calls to raise(),
// so we use a mutex to prevent concurrent calls to raise() and sigaction().
_PyMutex_lock(&signal_mutex);
e = PyOS_setsig(signalnum, func);
_PyMutex_unlock(&signal_mutex);

if (e == SIG_ERR) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
Expand Down

0 comments on commit 0e0b389

Please sign in to comment.