If no, I have ways I can workaround in PyO3. But I worry about edge cases like a signal handler being hit inside of tp_traverse, maybe in that case code will need to check whether it is attached to the interpreter (with PyThreadStateGetUnchecked?) and then if not, safely fail to attach until the traverse has finished.
I could be convinced otherwise, but at least for now I think that changing PyThreadState_GetUnchecked() to return NULL during tp_traverse introduces mores risks than it avoids.
I get that PyO3 wants to enforce correctness invariants, but I'm not sure you can do this thoroughly for tp_traverse. The restriction we stated was "no side effects". There are a number of macros or code patterns that don't have side effects, but would be unsafe to perform without a valid thread state:
Py_VISIT(Py_TYPE(self))
Py_VISIT(self->ob_item[i])
But I worry about edge cases like a signal handler being hit inside of tp_traverse
I don't think it's safe to call into Python APIs during a signal handler regardless of tp_traverse.
My latest thinking on this is that PyO3 will for now have tp_traverse be unsafe to implement by hand (although we're working on a macro to do it automatically so most users won't have to write unsafe code).
With this in mind, it seems like it's probably worth just leaving things as-is.
Activity
colesbury commented on Dec 19, 2025
I could be convinced otherwise, but at least for now I think that changing PyThreadState_GetUnchecked() to return NULL during tp_traverse introduces mores risks than it avoids.
I get that PyO3 wants to enforce correctness invariants, but I'm not sure you can do this thoroughly for tp_traverse. The restriction we stated was "no side effects". There are a number of macros or code patterns that don't have side effects, but would be unsafe to perform without a valid thread state:
I don't think it's safe to call into Python APIs during a signal handler regardless of tp_traverse.
davidhewitt commented on Aug 25, 2026
My latest thinking on this is that PyO3 will for now have tp_traverse be unsafe to implement by hand (although we're working on a macro to do it automatically so most users won't have to write unsafe code).
With this in mind, it seems like it's probably worth just leaving things as-is.