From 8fb02b6e1942811c8d81041e7df3f5f1f4b1d410 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 13 Mar 2020 23:38:08 +0100 Subject: [PATCH] bpo-39947: Add PyThreadState_GetInterpreter() (GH-18981) Add PyThreadState_GetInterpreter(tstate): get the interpreter of a Python thread state. --- Doc/c-api/init.rst | 19 ++++++++++++++----- Doc/whatsnew/3.9.rst | 3 ++- Include/pystate.h | 5 +++++ .../2020-03-13-18-10-58.bpo-39947.gmEAaU.rst | 2 ++ Modules/faulthandler.c | 6 +++--- Python/pystate.c | 11 +++++++++++ 6 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-03-13-18-10-58.bpo-39947.gmEAaU.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 661ed59ceb9..f309ad0c03c 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1064,12 +1064,21 @@ All of the following functions must be called after :c:func:`Py_Initialize`. :c:func:`PyThreadState_Clear`. - .. c:function:: void PyThreadState_DeleteCurrent() +.. c:function:: void PyThreadState_DeleteCurrent(void) - Destroy the current thread state and release the global interpreter lock. - Like :c:func:`PyThreadState_Delete`, the global interpreter lock need not - be held. The thread state must have been reset with a previous call - to :c:func:`PyThreadState_Clear`. + Destroy the current thread state and release the global interpreter lock. + Like :c:func:`PyThreadState_Delete`, the global interpreter lock need not + be held. The thread state must have been reset with a previous call + to :c:func:`PyThreadState_Clear`. + + +.. c:function:: PyInterpreterState* PyThreadState_GetInterpreter(PyThreadState *tstate) + + Get the interpreter of the Python thread state *tstate*. + + *tstate* must not be ``NULL``. + + .. versionadded:: 3.9 .. c:function:: PyInterpreterState* PyInterpreterState_Get(void) diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 4373e37f55e..4ef82feba19 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -406,7 +406,8 @@ Optimizations Build and C API Changes ======================= -* New :c:func:`PyInterpreterState_Get` function. +* New :c:func:`PyThreadState_GetInterpreter` and + :c:func:`PyInterpreterState_Get` functions to get the interpreter. * Add ``--with-platlibdir`` option to the ``configure`` script: name of the platform-specific library directory, stored in the new :attr:`sys.platlibdir` diff --git a/Include/pystate.h b/Include/pystate.h index 57dc9e45a78..70d3bdc9a78 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -87,6 +87,11 @@ PyAPI_FUNC(PyThreadState *) PyThreadState_Swap(PyThreadState *); PyAPI_FUNC(PyObject *) PyThreadState_GetDict(void); PyAPI_FUNC(int) PyThreadState_SetAsyncExc(unsigned long, PyObject *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000 +/* New in 3.9 */ +PyAPI_FUNC(PyInterpreterState *) PyThreadState_GetInterpreter(PyThreadState *tstate); +#endif + typedef enum {PyGILState_LOCKED, PyGILState_UNLOCKED} PyGILState_STATE; diff --git a/Misc/NEWS.d/next/C API/2020-03-13-18-10-58.bpo-39947.gmEAaU.rst b/Misc/NEWS.d/next/C API/2020-03-13-18-10-58.bpo-39947.gmEAaU.rst new file mode 100644 index 00000000000..668cdbcc171 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-03-13-18-10-58.bpo-39947.gmEAaU.rst @@ -0,0 +1,2 @@ +Add :c:func:`PyThreadState_GetInterpreter`: get the interpreter of a Python +thread state. diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c index 555e1afc9f8..ba88d980892 100644 --- a/Modules/faulthandler.c +++ b/Modules/faulthandler.c @@ -540,7 +540,7 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs) Py_XSETREF(fatal_error.file, file); fatal_error.fd = fd; fatal_error.all_threads = all_threads; - fatal_error.interp = tstate->interp; + fatal_error.interp = PyThreadState_GetInterpreter(tstate); if (faulthandler_enable() < 0) { return NULL; @@ -756,7 +756,7 @@ faulthandler_dump_traceback_later(PyObject *self, /* the downcast is safe: we check that 0 < timeout_us < PY_TIMEOUT_MAX */ thread.timeout_us = (PY_TIMEOUT_T)timeout_us; thread.repeat = repeat; - thread.interp = tstate->interp; + thread.interp = PyThreadState_GetInterpreter(tstate); thread.exit = exit; thread.header = header; thread.header_len = header_len; @@ -939,7 +939,7 @@ faulthandler_register_py(PyObject *self, user->fd = fd; user->all_threads = all_threads; user->chain = chain; - user->interp = tstate->interp; + user->interp = PyThreadState_GetInterpreter(tstate); user->enabled = 1; Py_RETURN_NONE; diff --git a/Python/pystate.c b/Python/pystate.c index 28c55786644..f92c2b4c5e2 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -998,6 +998,17 @@ PyThreadState_GetDict(void) } +PyInterpreterState * +PyThreadState_GetInterpreter(PyThreadState *tstate) +{ + assert(tstate != NULL); + if (tstate == NULL) { + return NULL; + } + return tstate->interp; +} + + /* Asynchronously raise an exception in a thread. Requested by Just van Rossum and Alex Martelli. To prevent naive misuse, you must write your own extension