From be79373a78c0d75fc715ab64253c9b757987a848 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 13 Mar 2020 18:15:33 +0100 Subject: [PATCH] bpo-39947: Add PyInterpreterState_Get() function (GH-18979) * Rename _PyInterpreterState_Get() to PyInterpreterState_Get() and move it the limited C API. * Add _PyInterpreterState_Get() alias to PyInterpreterState_Get() for backward compatibility with Python 3.8. --- Doc/c-api/init.rst | 12 ++++++++++++ Doc/whatsnew/3.9.rst | 2 ++ Include/cpython/pystate.h | 9 ++------- Include/pystate.h | 11 +++++++++++ .../C API/2020-03-13-17-43-00.bpo-39947.1Cu_d2.rst | 1 + Modules/_posixsubprocess.c | 2 +- Modules/_xxsubinterpretersmodule.c | 6 +++--- Python/pystate.c | 6 +++--- 8 files changed, 35 insertions(+), 14 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-03-13-17-43-00.bpo-39947.1Cu_d2.rst diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst index 747278c60b0..661ed59ceb9 100644 --- a/Doc/c-api/init.rst +++ b/Doc/c-api/init.rst @@ -1072,6 +1072,18 @@ All of the following functions must be called after :c:func:`Py_Initialize`. to :c:func:`PyThreadState_Clear`. +.. c:function:: PyInterpreterState* PyInterpreterState_Get(void) + + Get the current interpreter. + + Issue a fatal error if there no current Python thread state or no current + interpreter. It cannot return NULL. + + The caller must hold the GIL. + + .. versionadded:: 3.9 + + .. c:function:: PY_INT64_T PyInterpreterState_GetID(PyInterpreterState *interp) Return the interpreter's unique ID. If there was any error in doing diff --git a/Doc/whatsnew/3.9.rst b/Doc/whatsnew/3.9.rst index 0b61fb8f0de..4373e37f55e 100644 --- a/Doc/whatsnew/3.9.rst +++ b/Doc/whatsnew/3.9.rst @@ -406,6 +406,8 @@ Optimizations Build and C API Changes ======================= +* New :c:func:`PyInterpreterState_Get` function. + * Add ``--with-platlibdir`` option to the ``configure`` script: name of the platform-specific library directory, stored in the new :attr:`sys.platlibdir` attribute. See :attr:`sys.platlibdir` attribute for more information. diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index fbb0899186f..96df0d91fb5 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -139,13 +139,8 @@ struct _ts { }; -/* Get the current interpreter state. - - Issue a fatal error if there no current Python thread state or no current - interpreter. It cannot return NULL. - - The caller must hold the GIL.*/ -PyAPI_FUNC(PyInterpreterState *) _PyInterpreterState_Get(void); +// Alias for backward compatibility with Python 3.8 +#define _PyInterpreterState_Get PyInterpreterState_Get PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *); diff --git a/Include/pystate.h b/Include/pystate.h index 1cb2305696f..57dc9e45a78 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -28,6 +28,17 @@ PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void); PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *); PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *); +#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03090000 +/* New in 3.9 */ +/* Get the current interpreter state. + + Issue a fatal error if there no current Python thread state or no current + interpreter. It cannot return NULL. + + The caller must hold the GIL. */ +PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_Get(void); +#endif + #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03080000 /* New in 3.8 */ PyAPI_FUNC(PyObject *) PyInterpreterState_GetDict(PyInterpreterState *); diff --git a/Misc/NEWS.d/next/C API/2020-03-13-17-43-00.bpo-39947.1Cu_d2.rst b/Misc/NEWS.d/next/C API/2020-03-13-17-43-00.bpo-39947.1Cu_d2.rst new file mode 100644 index 00000000000..c7184be7580 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-03-13-17-43-00.bpo-39947.1Cu_d2.rst @@ -0,0 +1 @@ +Add :c:func:`PyInterpreterState_Get` function to the limited C API. diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c index 2aed79e14c4..f9919c3ab4f 100644 --- a/Modules/_posixsubprocess.c +++ b/Modules/_posixsubprocess.c @@ -635,7 +635,7 @@ subprocess_fork_exec(PyObject* self, PyObject *args) return NULL; if ((preexec_fn != Py_None) && - (_PyInterpreterState_Get() != PyInterpreterState_Main())) { + (PyInterpreterState_Get() != PyInterpreterState_Main())) { PyErr_SetString(PyExc_RuntimeError, "preexec_fn not supported within subinterpreters"); return NULL; diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index cc4f5d9e6dc..526115a6826 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -26,9 +26,9 @@ _copy_raw_string(PyObject *strobj) static PyInterpreterState * _get_current(void) { - // _PyInterpreterState_Get() aborts if lookup fails, so don't need + // PyInterpreterState_Get() aborts if lookup fails, so don't need // to check the result for NULL. - return _PyInterpreterState_Get(); + return PyInterpreterState_Get(); } @@ -1928,7 +1928,7 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr, // Switch to interpreter. PyThreadState *save_tstate = NULL; - if (interp != _PyInterpreterState_Get()) { + if (interp != PyInterpreterState_Get()) { // XXX Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); // XXX Possible GILState issues? diff --git a/Python/pystate.c b/Python/pystate.c index 9cf6bea1a02..28c55786644 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -396,7 +396,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) PyInterpreterState * -_PyInterpreterState_Get(void) +PyInterpreterState_Get(void) { PyThreadState *tstate = _PyThreadState_GET(); if (tstate == NULL) { @@ -1423,9 +1423,9 @@ _check_xidata(_PyCrossInterpreterData *data) int _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data) { - // _PyInterpreterState_Get() aborts if lookup fails, so we don't need + // PyInterpreterState_Get() aborts if lookup fails, so we don't need // to check the result for NULL. - PyInterpreterState *interp = _PyInterpreterState_Get(); + PyInterpreterState *interp = PyInterpreterState_Get(); // Reset data before re-populating. *data = (_PyCrossInterpreterData){0};