gh-108867: Add PyThreadState_GetUnchecked() function (#108870)

Add PyThreadState_GetUnchecked() function: similar to
PyThreadState_Get(), but don't issue a fatal error if it is NULL. The
caller is responsible to check if the result is NULL. Previously,
this function was private and known as _PyThreadState_UncheckedGet().
This commit is contained in:
Victor Stinner 2023-10-03 18:53:51 +02:00 committed by GitHub
parent 6ab6040054
commit d73501602f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 34 additions and 8 deletions

View file

@ -870,6 +870,19 @@ code, or when embedding the Python interpreter:
When the current thread state is ``NULL``, this issues a fatal error (so that
the caller needn't check for ``NULL``).
See also :c:func:`PyThreadState_GetUnchecked`.
.. c:function:: PyThreadState* PyThreadState_GetUnchecked()
Similar to :c:func:`PyThreadState_Get`, but don't kill the process with a
fatal error if it is NULL. The caller is responsible to check if the result
is NULL.
.. versionadded:: 3.13
In Python 3.5 to 3.12, the function was private and known as
``_PyThreadState_UncheckedGet()``.
.. c:function:: PyThreadState* PyThreadState_Swap(PyThreadState *tstate)

View file

@ -1003,6 +1003,13 @@ New Features
functions on Python 3.11 and 3.12.
(Contributed by Victor Stinner in :gh:`107073`.)
* Add :c:func:`PyThreadState_GetUnchecked()` function: similar to
:c:func:`PyThreadState_Get()`, but don't kill the process with a fatal error
if it is NULL. The caller is responsible to check if the result is NULL.
Previously, the function was private and known as
``_PyThreadState_UncheckedGet()``.
(Contributed by Victor Stinner in :gh:`108867`.)
Porting to Python 3.13
----------------------

View file

@ -425,7 +425,7 @@ PyAPI_FUNC(int) _PyTrash_cond(PyObject *op, destructor dealloc);
/* If "cond" is false, then _tstate remains NULL and the deallocator \
* is run normally without involving the trashcan */ \
if (cond) { \
_tstate = _PyThreadState_UncheckedGet(); \
_tstate = PyThreadState_GetUnchecked(); \
if (_PyTrash_begin(_tstate, _PyObject_CAST(op))) { \
break; \
} \

View file

@ -218,7 +218,7 @@ struct _ts {
/* Similar to PyThreadState_Get(), but don't issue a fatal error
* if it is NULL. */
PyAPI_FUNC(PyThreadState *) _PyThreadState_UncheckedGet(void);
PyAPI_FUNC(PyThreadState *) PyThreadState_GetUnchecked(void);
// Disable tracing and profiling.

View file

@ -93,7 +93,7 @@ PyAPI_FUNC(PyThreadState *) _PyThreadState_GetCurrent(void);
The caller must hold the GIL.
See also PyThreadState_Get() and _PyThreadState_UncheckedGet(). */
See also PyThreadState_Get() and PyThreadState_GetUnchecked(). */
static inline PyThreadState*
_PyThreadState_GET(void)
{

View file

@ -56,7 +56,7 @@ PyAPI_FUNC(void) PyThreadState_Delete(PyThreadState *);
The caller must hold the GIL.
See also _PyThreadState_UncheckedGet() and _PyThreadState_GET(). */
See also PyThreadState_GetUnchecked() and _PyThreadState_GET(). */
PyAPI_FUNC(PyThreadState *) PyThreadState_Get(void);
// Alias to PyThreadState_Get()

View file

@ -0,0 +1,5 @@
Add :c:func:`PyThreadState_GetUnchecked()` function: similar to
:c:func:`PyThreadState_Get()`, but don't kill the process with a fatal error if
it is NULL. The caller is responsible to check if the result is NULL.
Previously, the function was private and known as
``_PyThreadState_UncheckedGet()``. Patch by Victor Stinner.

View file

@ -2458,8 +2458,8 @@ test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args))
PyThreadState *tstate2 = PyThreadState_Get();
assert(tstate2 == tstate);
// private _PyThreadState_UncheckedGet()
PyThreadState *tstate3 = _PyThreadState_UncheckedGet();
// PyThreadState_GetUnchecked()
PyThreadState *tstate3 = PyThreadState_GetUnchecked();
assert(tstate3 == tstate);
// PyThreadState_EnterTracing(), PyThreadState_LeaveTracing()

View file

@ -6,6 +6,7 @@
#include "pycore_pathconfig.h" // _PyPathConfig_ReadGlobal()
#include "pycore_pyerrors.h" // _PyErr_WriteUnraisableMsg()
#include "pycore_pymem.h" // _PyMem_RawWcsdup()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "marshal.h" // PyMarshal_ReadObjectFromString
#include "osdefs.h" // DELIM
@ -821,7 +822,7 @@ _PyConfig_InitPathConfig(PyConfig *config, int compute_path_config)
return status;
}
if (!_PyThreadState_UncheckedGet()) {
if (!_PyThreadState_GET()) {
return PyStatus_Error("cannot calculate path configuration without GIL");
}

View file

@ -1908,7 +1908,7 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
//---------------------------------
PyThreadState *
_PyThreadState_UncheckedGet(void)
PyThreadState_GetUnchecked(void)
{
return current_fast_get(&_PyRuntime);
}