Skip to content

signalmodule.c in free-threaded Python #161235

Open

Description

@johng

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.

Activity

  1. johng commented on Nov 3, 2026

    @johng
    ContributorAuthor

    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;
    }
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions