Skip to content

Commit 0e0b389

Browse files
committed
signalmodule: fix thread-safety issue on macOS
The sigaction function is not safe to call concurrently with raise() on macOS.
1 parent ada9b73 commit 0e0b389

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

Modules/signalmodule.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ typedef struct {
122122
PyTypeObject *siginfo_type;
123123
} _signal_module_state;
124124

125+
static _PyMutex signal_mutex;
125126

126127
Py_LOCAL_INLINE(PyObject *)
127128
get_handler(int i)
@@ -437,9 +438,11 @@ signal_raise_signal_impl(PyObject *module, int signalnum)
437438
{
438439
int err;
439440
Py_BEGIN_ALLOW_THREADS
441+
_PyMutex_lock(&signal_mutex);
440442
_Py_BEGIN_SUPPRESS_IPH
441443
err = raise(signalnum);
442444
_Py_END_SUPPRESS_IPH
445+
_PyMutex_unlock(&signal_mutex);
443446
Py_END_ALLOW_THREADS
444447

445448
if (err) {
@@ -479,6 +482,7 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
479482
_signal_module_state *modstate = get_signal_state(module);
480483
PyObject *old_handler;
481484
void (*func)(int);
485+
PyOS_sighandler_t e;
482486
#ifdef MS_WINDOWS
483487
/* Validate that signalnum is one of the allowable signals */
484488
switch (signalnum) {
@@ -528,7 +532,14 @@ signal_signal_impl(PyObject *module, int signalnum, PyObject *handler)
528532
if (_PyErr_CheckSignalsTstate(tstate)) {
529533
return NULL;
530534
}
531-
if (PyOS_setsig(signalnum, func) == SIG_ERR) {
535+
536+
// On macOS, sigaction isn't thread-safe with concurrent calls to raise(),
537+
// so we use a mutex to prevent concurrent calls to raise() and sigaction().
538+
_PyMutex_lock(&signal_mutex);
539+
e = PyOS_setsig(signalnum, func);
540+
_PyMutex_unlock(&signal_mutex);
541+
542+
if (e == SIG_ERR) {
532543
PyErr_SetFromErrno(PyExc_OSError);
533544
return NULL;
534545
}

0 commit comments

Comments
 (0)