You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This issue is intended to track discussion on signalmodule.c for free-treaded Python as a spin off issues from #116738 given it way create some wider discussion on the best approach. And also a const benefit analysis of any additional checks or required re-design.
An initial audit with TSAN/code review exposed some issues.
Issue
Where
What goes wrong
signal.getsignal use-after-free
signal_getsignal_impl vs signal_signal_impl
Reader loads a handler pointer it doesn't own; main thread swaps and frees it before the reader increfs
wakeup.fd data race
trip_signal vs set_wakeup_fd
One plain int read and written by two threads with no ordering
PyErr_SetInterruptEx borrowed read
PyErr_SetInterruptEx
Reads and compares a handler pointer that another thread may have freed
However per #161221 (comment) and linked post https://iafisher.com/2026/08/sigprint any mechanism to improve safety "bolted on" would be very hard get right due to the interrupt mechanism that is able to run at any time.
One approach I've looked at for getsignal UAF is using _PyObject_XDecRefDelayed on the old handler which is also atomically swapped and relying on QSBR. It does not fully solve PyErr_SetInterruptEx since it can be called from C, although this might be a gap with GIL python too.
swap_handler(int i, PyObject *func)
{
/* Store func with an atomic operation to ensure
that PyErr_SetInterrupt is async-signal-safe. */
PyObject *old = _Py_atomic_exchange_ptr(&Handlers[i].func,
Py_XNewRef(func));
PyObject *result = Py_XNewRef(old);
_PyObject_XDecRefDelayed(old);
return result;
}
Activity
johng commentedon Nov 3, 2026
One approach I've looked at for
getsignalUAF is using_PyObject_XDecRefDelayedon the old handler which is also atomically swapped and relying on QSBR. It does not fully solvePyErr_SetInterruptExsince it can be called from C, although this might be a gap with GIL python too.