Thread argument for exc_info and public API
Hi there, I've been poking around the thread state API and error/exception handling, and there's something missing I'd like to see happening. The only way to retrieve the current exception is via sys.excinfo or PyErr_GetExcInfo in C. However, the issue is that they don't take a PyThreadState as argument, but use _PyThreadState_GET() to retrieve the thread state. That makes it impossible to retrieve the exception information for a different thread than the one calling the function. In order to retrieve the exception from *any* PyThreadState, the caller has to use _PyErr_GetTopmostException which takes a PyThreadState as argument — though that function is private and therefore not documented or usable in an external module (in theory at least). Should we make _PyErr_GetTopmostException public, or implement something different to retrieve the top most exception from a PyThreadState? Cheers, -- Julien Danjou # Free Software hacker # https://julien.danjou.info
Hi,
Le mer. 18 déc. 2019 à 16:43, Julien Danjou
The only way to retrieve the current exception is via sys.excinfo or PyErr_GetExcInfo in C. However, the issue is that they don't take a PyThreadState as argument, but use _PyThreadState_GET() to retrieve the thread state.
If we add the following function, does it solve your use case? void _PyErr_GetExcInfo(PyThreadState *tstate, PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
In order to retrieve the exception from *any* PyThreadState, the caller has to use _PyErr_GetTopmostException which takes a PyThreadState as argument — though that function is private and therefore not documented or usable in an external module (in theory at least).
What if this function is exported as a private function? Usually, functions in Python header files are prefixed by PyAPI_FUNC(), but for an unknown reason, this one is not: _PyErr_StackItem *_PyErr_GetTopmostException(PyThreadState *tstate); Maybe it's because the author didn't want to expose the private _PyErr_StackItem structure?
Should we make _PyErr_GetTopmostException public, or implement something different to retrieve the top most exception from a PyThreadState?
IMHO a _PyErr_GetExcInfo() function taking a tstate parameter is a better idea than exposing the private _PyErr_StackItem structure. Private functions *can* be used for debuggers, but we don't provide any warranty that the function is not going to disappear. Such functions have been moved to the internal API for example. The internal C API *can* be used, but you have to opt-in so you know that you get unstable APIs :-) Victor -- Night gathers, and now my watch begins. It shall not end until my death.
On Fri, Dec 20 2019, Victor Stinner wrote: Hi Victor,
If we add the following function, does it solve your use case?
void _PyErr_GetExcInfo(PyThreadState *tstate, PyObject **p_type, PyObject **p_value, PyObject **p_traceback)
Yes, it would.
In order to retrieve the exception from *any* PyThreadState, the caller has to use _PyErr_GetTopmostException which takes a PyThreadState as argument — though that function is private and therefore not documented or usable in an external module (in theory at least).
What if this function is exported as a private function? Usually, functions in Python header files are prefixed by PyAPI_FUNC(), but for an unknown reason, this one is not:
_PyErr_StackItem *_PyErr_GetTopmostException(PyThreadState *tstate);
Maybe it's because the author didn't want to expose the private _PyErr_StackItem structure?
This is my guess too. It'd make sense since this was struct was introduced around 3.7 and those values where just stored inside PyThreadState before. I guess nobody wanted to commit to an API. I don't think exposing _PyErr_StackItem is worth it. It's just a placeholder for the usual exception triplet (tp, value, tb).
Should we make _PyErr_GetTopmostException public, or implement something different to retrieve the top most exception from a PyThreadState?
IMHO a _PyErr_GetExcInfo() function taking a tstate parameter is a better idea than exposing the private _PyErr_StackItem structure.
I agree.
Private functions *can* be used for debuggers, but we don't provide any warranty that the function is not going to disappear. Such functions have been moved to the internal API for example. The internal C API *can* be used, but you have to opt-in so you know that you get unstable APIs :-)
Alright! I didn't know that you could use private functions. I'm totally in the debugger case so it's fine with me. :) I'll come up with a patch that exposes _PyErr_GetExcInfo() as you suggested. Thanks Victor! -- Julien Danjou // Free Software hacker // https://julien.danjou.info
participants (2)
-
Julien Danjou
-
Victor Stinner