mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
gh-128360: Add _Py_AssertHoldsTstate
as assertion for holding a thread state (#128361)
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
parent
c6b570e5e3
commit
4d0a6595a0
11 changed files with 48 additions and 32 deletions
|
@ -300,6 +300,19 @@ PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
|
||||||
// See also PyInterpreterState_Get() and _PyInterpreterState_GET().
|
// See also PyInterpreterState_Get() and _PyInterpreterState_GET().
|
||||||
extern PyInterpreterState* _PyGILState_GetInterpreterStateUnsafe(void);
|
extern PyInterpreterState* _PyGILState_GetInterpreterStateUnsafe(void);
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
/* Modern equivalent of assert(PyGILState_Check()) */
|
||||||
|
static inline void
|
||||||
|
_Py_AssertHoldsTstateFunc(const char *func)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
_Py_EnsureFuncTstateNotNULL(func, tstate);
|
||||||
|
}
|
||||||
|
#define _Py_AssertHoldsTstate() _Py_AssertHoldsTstateFunc(__func__)
|
||||||
|
#else
|
||||||
|
#define _Py_AssertHoldsTstate()
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -110,6 +110,7 @@ Local naming conventions:
|
||||||
#include "pycore_fileutils.h" // _Py_set_inheritable()
|
#include "pycore_fileutils.h" // _Py_set_inheritable()
|
||||||
#include "pycore_moduleobject.h" // _PyModule_GetState
|
#include "pycore_moduleobject.h" // _PyModule_GetState
|
||||||
#include "pycore_time.h" // _PyTime_AsMilliseconds()
|
#include "pycore_time.h" // _PyTime_AsMilliseconds()
|
||||||
|
#include "pycore_pystate.h" // _Py_AssertHoldsTstate()
|
||||||
#include "pycore_pyatomic_ft_wrappers.h"
|
#include "pycore_pyatomic_ft_wrappers.h"
|
||||||
|
|
||||||
#ifdef _Py_MEMORY_SANITIZER
|
#ifdef _Py_MEMORY_SANITIZER
|
||||||
|
@ -822,8 +823,8 @@ internal_select(PySocketSockObject *s, int writing, PyTime_t interval,
|
||||||
struct timeval tv, *tvp;
|
struct timeval tv, *tvp;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* must be called with the GIL held */
|
/* must be called with a thread state */
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
/* Error condition is for output only */
|
/* Error condition is for output only */
|
||||||
assert(!(connect && !writing));
|
assert(!(connect && !writing));
|
||||||
|
@ -936,8 +937,8 @@ sock_call_ex(PySocketSockObject *s,
|
||||||
int deadline_initialized = 0;
|
int deadline_initialized = 0;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
/* sock_call() must be called with the GIL held. */
|
/* sock_call() must be called with a thread state. */
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
/* outer loop to retry select() when select() is interrupted by a signal
|
/* outer loop to retry select() when select() is interrupted by a signal
|
||||||
or to retry select()+sock_func() on false positive (see above) */
|
or to retry select()+sock_func() on false positive (see above) */
|
||||||
|
|
|
@ -3073,14 +3073,14 @@ _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
|
||||||
}
|
}
|
||||||
|
|
||||||
int PyRefTracer_SetTracer(PyRefTracer tracer, void *data) {
|
int PyRefTracer_SetTracer(PyRefTracer tracer, void *data) {
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
_PyRuntime.ref_tracer.tracer_func = tracer;
|
_PyRuntime.ref_tracer.tracer_func = tracer;
|
||||||
_PyRuntime.ref_tracer.tracer_data = data;
|
_PyRuntime.ref_tracer.tracer_data = data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyRefTracer PyRefTracer_GetTracer(void** data) {
|
PyRefTracer PyRefTracer_GetTracer(void** data) {
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
if (data != NULL) {
|
if (data != NULL) {
|
||||||
*data = _PyRuntime.ref_tracer.tracer_data;
|
*data = _PyRuntime.ref_tracer.tracer_data;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2909,7 +2909,8 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
|
||||||
static inline void
|
static inline void
|
||||||
_PyMem_DebugCheckGIL(const char *func)
|
_PyMem_DebugCheckGIL(const char *func)
|
||||||
{
|
{
|
||||||
if (!PyGILState_Check()) {
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
if (tstate == NULL) {
|
||||||
#ifndef Py_GIL_DISABLED
|
#ifndef Py_GIL_DISABLED
|
||||||
_Py_FatalErrorFunc(func,
|
_Py_FatalErrorFunc(func,
|
||||||
"Python memory allocator called "
|
"Python memory allocator called "
|
||||||
|
|
|
@ -995,7 +995,7 @@ _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, uintptr_t bit)
|
||||||
void
|
void
|
||||||
_Py_FinishPendingCalls(PyThreadState *tstate)
|
_Py_FinishPendingCalls(PyThreadState *tstate)
|
||||||
{
|
{
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
assert(_PyThreadState_CheckConsistency(tstate));
|
assert(_PyThreadState_CheckConsistency(tstate));
|
||||||
|
|
||||||
struct _pending_calls *pending = &tstate->interp->ceval.pending;
|
struct _pending_calls *pending = &tstate->interp->ceval.pending;
|
||||||
|
@ -1056,7 +1056,7 @@ _PyEval_MakePendingCalls(PyThreadState *tstate)
|
||||||
int
|
int
|
||||||
Py_MakePendingCalls(void)
|
Py_MakePendingCalls(void)
|
||||||
{
|
{
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
assert(_PyThreadState_CheckConsistency(tstate));
|
assert(_PyThreadState_CheckConsistency(tstate));
|
||||||
|
|
|
@ -314,8 +314,8 @@ _PyErr_SetLocaleString(PyObject *exception, const char *string)
|
||||||
PyObject* _Py_HOT_FUNCTION
|
PyObject* _Py_HOT_FUNCTION
|
||||||
PyErr_Occurred(void)
|
PyErr_Occurred(void)
|
||||||
{
|
{
|
||||||
/* The caller must hold the GIL. */
|
/* The caller must hold a thread state. */
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
return _PyErr_Occurred(tstate);
|
return _PyErr_Occurred(tstate);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_fileutils.h" // fileutils definitions
|
#include "pycore_fileutils.h" // fileutils definitions
|
||||||
#include "pycore_runtime.h" // _PyRuntime
|
#include "pycore_runtime.h" // _PyRuntime
|
||||||
|
#include "pycore_pystate.h" // _Py_AssertHoldsTstate()
|
||||||
#include "osdefs.h" // SEP
|
#include "osdefs.h" // SEP
|
||||||
|
|
||||||
#include <stdlib.h> // mbstowcs()
|
#include <stdlib.h> // mbstowcs()
|
||||||
|
@ -1311,7 +1312,7 @@ _Py_fstat(int fd, struct _Py_stat_struct *status)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS
|
Py_BEGIN_ALLOW_THREADS
|
||||||
res = _Py_fstat_noraise(fd, status);
|
res = _Py_fstat_noraise(fd, status);
|
||||||
|
@ -1691,7 +1692,7 @@ int
|
||||||
_Py_open(const char *pathname, int flags)
|
_Py_open(const char *pathname, int flags)
|
||||||
{
|
{
|
||||||
/* _Py_open() must be called with the GIL held. */
|
/* _Py_open() must be called with the GIL held. */
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
return _Py_open_impl(pathname, flags, 1);
|
return _Py_open_impl(pathname, flags, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1766,7 +1767,7 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
|
||||||
FILE*
|
FILE*
|
||||||
Py_fopen(PyObject *path, const char *mode)
|
Py_fopen(PyObject *path, const char *mode)
|
||||||
{
|
{
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
|
if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1881,7 +1882,7 @@ _Py_read(int fd, void *buf, size_t count)
|
||||||
int err;
|
int err;
|
||||||
int async_err = 0;
|
int async_err = 0;
|
||||||
|
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
/* _Py_read() must not be called with an exception set, otherwise the
|
/* _Py_read() must not be called with an exception set, otherwise the
|
||||||
* caller may think that read() was interrupted by a signal and the signal
|
* caller may think that read() was interrupted by a signal and the signal
|
||||||
|
@ -2047,7 +2048,7 @@ _Py_write_impl(int fd, const void *buf, size_t count, int gil_held)
|
||||||
Py_ssize_t
|
Py_ssize_t
|
||||||
_Py_write(int fd, const void *buf, size_t count)
|
_Py_write(int fd, const void *buf, size_t count)
|
||||||
{
|
{
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
/* _Py_write() must not be called with an exception set, otherwise the
|
/* _Py_write() must not be called with an exception set, otherwise the
|
||||||
* caller may think that write() was interrupted by a signal and the signal
|
* caller may think that write() was interrupted by a signal and the signal
|
||||||
|
@ -2675,7 +2676,7 @@ _Py_dup(int fd)
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
handle = _Py_get_osfhandle(fd);
|
handle = _Py_get_osfhandle(fd);
|
||||||
|
|
|
@ -491,8 +491,8 @@ int
|
||||||
_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
_PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
||||||
{
|
{
|
||||||
assert(is_tstate_valid(tstate));
|
assert(is_tstate_valid(tstate));
|
||||||
/* The caller must hold the GIL */
|
/* The caller must hold a thread state */
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
/* Call _PySys_Audit() in the context of the current thread state,
|
/* Call _PySys_Audit() in the context of the current thread state,
|
||||||
even if tstate is not the current thread state. */
|
even if tstate is not the current thread state. */
|
||||||
|
@ -586,8 +586,8 @@ int
|
||||||
_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
_PyEval_SetTrace(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
|
||||||
{
|
{
|
||||||
assert(is_tstate_valid(tstate));
|
assert(is_tstate_valid(tstate));
|
||||||
/* The caller must hold the GIL */
|
/* The caller must hold a thread state */
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
/* Call _PySys_Audit() in the context of the current thread state,
|
/* Call _PySys_Audit() in the context of the current thread state,
|
||||||
even if tstate is not the current thread state. */
|
even if tstate is not the current thread state. */
|
||||||
|
|
|
@ -2897,7 +2897,6 @@ _PyInterpreterState_GetConfigCopy(PyConfig *config)
|
||||||
const PyConfig*
|
const PyConfig*
|
||||||
_Py_GetConfig(void)
|
_Py_GetConfig(void)
|
||||||
{
|
{
|
||||||
assert(PyGILState_Check());
|
|
||||||
PyThreadState *tstate = current_fast_get();
|
PyThreadState *tstate = current_fast_get();
|
||||||
_Py_EnsureTstateNotNULL(tstate);
|
_Py_EnsureTstateNotNULL(tstate);
|
||||||
return _PyInterpreterState_GetConfig(tstate->interp);
|
return _PyInterpreterState_GetConfig(tstate->interp);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_time.h" // PyTime_t
|
#include "pycore_time.h" // PyTime_t
|
||||||
|
#include "pycore_pystate.h" // _Py_AssertHoldsTstate()
|
||||||
|
|
||||||
#include <time.h> // gmtime_r()
|
#include <time.h> // gmtime_r()
|
||||||
#ifdef HAVE_SYS_TIME_H
|
#ifdef HAVE_SYS_TIME_H
|
||||||
|
@ -897,14 +898,14 @@ _PyTime_AsTimespec(PyTime_t t, struct timespec *ts)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// N.B. If raise_exc=0, this may be called without the GIL.
|
// N.B. If raise_exc=0, this may be called without a thread state.
|
||||||
static int
|
static int
|
||||||
py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
|
py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
|
||||||
{
|
{
|
||||||
assert(info == NULL || raise_exc);
|
assert(info == NULL || raise_exc);
|
||||||
if (raise_exc) {
|
if (raise_exc) {
|
||||||
// raise_exc requires to hold the GIL
|
// raise_exc requires to hold a thread state
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
@ -1142,14 +1143,14 @@ py_mach_timebase_info(_PyTimeFraction *base, int raise_exc)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// N.B. If raise_exc=0, this may be called without the GIL.
|
// N.B. If raise_exc=0, this may be called without a thread state.
|
||||||
static int
|
static int
|
||||||
py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
|
py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
|
||||||
{
|
{
|
||||||
assert(info == NULL || raise_exc);
|
assert(info == NULL || raise_exc);
|
||||||
if (raise_exc) {
|
if (raise_exc) {
|
||||||
// raise_exc requires to hold the GIL
|
// raise_exc requires to hold a thread state
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(MS_WINDOWS)
|
#if defined(MS_WINDOWS)
|
||||||
|
|
|
@ -367,7 +367,7 @@ traceback_new(void)
|
||||||
traceback_t *traceback;
|
traceback_t *traceback;
|
||||||
_Py_hashtable_entry_t *entry;
|
_Py_hashtable_entry_t *entry;
|
||||||
|
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
/* get frames */
|
/* get frames */
|
||||||
traceback = tracemalloc_traceback;
|
traceback = tracemalloc_traceback;
|
||||||
|
@ -749,7 +749,7 @@ static void
|
||||||
tracemalloc_clear_traces_unlocked(void)
|
tracemalloc_clear_traces_unlocked(void)
|
||||||
{
|
{
|
||||||
// Clearing tracemalloc_filenames requires the GIL to call Py_DECREF()
|
// Clearing tracemalloc_filenames requires the GIL to call Py_DECREF()
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
|
|
||||||
set_reentrant(1);
|
set_reentrant(1);
|
||||||
|
|
||||||
|
@ -1302,7 +1302,7 @@ PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
|
||||||
void
|
void
|
||||||
_PyTraceMalloc_Fini(void)
|
_PyTraceMalloc_Fini(void)
|
||||||
{
|
{
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
tracemalloc_deinit();
|
tracemalloc_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,7 +1323,7 @@ _PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent event,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(PyGILState_Check());
|
_Py_AssertHoldsTstate();
|
||||||
TABLES_LOCK();
|
TABLES_LOCK();
|
||||||
|
|
||||||
if (!tracemalloc_config.tracing) {
|
if (!tracemalloc_config.tracing) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue