https://github.com/python/cpython/commit/4d0a6595a06c554c57ebd90ee64ff4c2bec239b8
commit: 4d0a6595a06c554c57ebd90ee64ff4c2bec239b8
branch: main
author: Peter Bierma <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-01-20T17:04:35+05:30
summary:

gh-128360: Add `_Py_AssertHoldsTstate` as assertion for holding a thread state 
(#128361)

Co-authored-by: Kumar Aditya <[email protected]>

files:
M Include/internal/pycore_pystate.h
M Modules/socketmodule.c
M Objects/object.c
M Objects/obmalloc.c
M Python/ceval_gil.c
M Python/errors.c
M Python/fileutils.c
M Python/legacy_tracing.c
M Python/pystate.c
M Python/pytime.c
M Python/tracemalloc.c

diff --git a/Include/internal/pycore_pystate.h 
b/Include/internal/pycore_pystate.h
index 1e73e541ef8de0..ff3b222b157810 100644
--- a/Include/internal/pycore_pystate.h
+++ b/Include/internal/pycore_pystate.h
@@ -300,6 +300,19 @@ PyAPI_FUNC(const PyConfig*) _Py_GetConfig(void);
 // See also PyInterpreterState_Get() and _PyInterpreterState_GET().
 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
 }
 #endif
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index e70aa304f2f3a3..5e81253ca4a591 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -110,6 +110,7 @@ Local naming conventions:
 #include "pycore_fileutils.h"     // _Py_set_inheritable()
 #include "pycore_moduleobject.h"  // _PyModule_GetState
 #include "pycore_time.h"          // _PyTime_AsMilliseconds()
+#include "pycore_pystate.h"       // _Py_AssertHoldsTstate()
 #include "pycore_pyatomic_ft_wrappers.h"
 
 #ifdef _Py_MEMORY_SANITIZER
@@ -822,8 +823,8 @@ internal_select(PySocketSockObject *s, int writing, 
PyTime_t interval,
     struct timeval tv, *tvp;
 #endif
 
-    /* must be called with the GIL held */
-    assert(PyGILState_Check());
+    /* must be called with a thread state */
+    _Py_AssertHoldsTstate();
 
     /* Error condition is for output only */
     assert(!(connect && !writing));
@@ -936,8 +937,8 @@ sock_call_ex(PySocketSockObject *s,
     int deadline_initialized = 0;
     int res;
 
-    /* sock_call() must be called with the GIL held. */
-    assert(PyGILState_Check());
+    /* sock_call() must be called with a thread state. */
+    _Py_AssertHoldsTstate();
 
     /* outer loop to retry select() when select() is interrupted by a signal
        or to retry select()+sock_func() on false positive (see above) */
diff --git a/Objects/object.c b/Objects/object.c
index 4e900d8e79d91a..51b6016b9c191c 100644
--- a/Objects/object.c
+++ b/Objects/object.c
@@ -3073,14 +3073,14 @@ _Py_SetRefcnt(PyObject *ob, Py_ssize_t refcnt)
 }
 
 int PyRefTracer_SetTracer(PyRefTracer tracer, void *data) {
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
     _PyRuntime.ref_tracer.tracer_func = tracer;
     _PyRuntime.ref_tracer.tracer_data = data;
     return 0;
 }
 
 PyRefTracer PyRefTracer_GetTracer(void** data) {
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
     if (data != NULL) {
         *data = _PyRuntime.ref_tracer.tracer_data;
     }
diff --git a/Objects/obmalloc.c b/Objects/obmalloc.c
index b103deb01ca712..5688049b024696 100644
--- a/Objects/obmalloc.c
+++ b/Objects/obmalloc.c
@@ -2909,7 +2909,8 @@ _PyMem_DebugRawRealloc(void *ctx, void *p, size_t nbytes)
 static inline void
 _PyMem_DebugCheckGIL(const char *func)
 {
-    if (!PyGILState_Check()) {
+    PyThreadState *tstate = _PyThreadState_GET();
+    if (tstate == NULL) {
 #ifndef Py_GIL_DISABLED
         _Py_FatalErrorFunc(func,
                            "Python memory allocator called "
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index 1f811e72406130..416eec01052224 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -995,7 +995,7 @@ _Py_unset_eval_breaker_bit_all(PyInterpreterState *interp, 
uintptr_t bit)
 void
 _Py_FinishPendingCalls(PyThreadState *tstate)
 {
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
     assert(_PyThreadState_CheckConsistency(tstate));
 
     struct _pending_calls *pending = &tstate->interp->ceval.pending;
@@ -1056,7 +1056,7 @@ _PyEval_MakePendingCalls(PyThreadState *tstate)
 int
 Py_MakePendingCalls(void)
 {
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
 
     PyThreadState *tstate = _PyThreadState_GET();
     assert(_PyThreadState_CheckConsistency(tstate));
diff --git a/Python/errors.c b/Python/errors.c
index b6ac2f767a283b..9c7b771133dcf4 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -314,8 +314,8 @@ _PyErr_SetLocaleString(PyObject *exception, const char 
*string)
 PyObject* _Py_HOT_FUNCTION
 PyErr_Occurred(void)
 {
-    /* The caller must hold the GIL. */
-    assert(PyGILState_Check());
+    /* The caller must hold a thread state. */
+    _Py_AssertHoldsTstate();
 
     PyThreadState *tstate = _PyThreadState_GET();
     return _PyErr_Occurred(tstate);
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 6bc3a44c3c1313..72804c39220591 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -1,6 +1,7 @@
 #include "Python.h"
 #include "pycore_fileutils.h"     // fileutils definitions
 #include "pycore_runtime.h"       // _PyRuntime
+#include "pycore_pystate.h"       // _Py_AssertHoldsTstate()
 #include "osdefs.h"               // SEP
 
 #include <stdlib.h>               // mbstowcs()
@@ -1311,7 +1312,7 @@ _Py_fstat(int fd, struct _Py_stat_struct *status)
 {
     int res;
 
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
 
     Py_BEGIN_ALLOW_THREADS
     res = _Py_fstat_noraise(fd, status);
@@ -1691,7 +1692,7 @@ int
 _Py_open(const char *pathname, int flags)
 {
     /* _Py_open() must be called with the GIL held. */
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
     return _Py_open_impl(pathname, flags, 1);
 }
 
@@ -1766,7 +1767,7 @@ _Py_wfopen(const wchar_t *path, const wchar_t *mode)
 FILE*
 Py_fopen(PyObject *path, const char *mode)
 {
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
 
     if (PySys_Audit("open", "Osi", path, mode, 0) < 0) {
         return NULL;
@@ -1881,7 +1882,7 @@ _Py_read(int fd, void *buf, size_t count)
     int err;
     int async_err = 0;
 
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
 
     /* _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
@@ -2047,7 +2048,7 @@ _Py_write_impl(int fd, const void *buf, size_t count, int 
gil_held)
 Py_ssize_t
 _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
      * caller may think that write() was interrupted by a signal and the signal
@@ -2675,7 +2676,7 @@ _Py_dup(int fd)
     HANDLE handle;
 #endif
 
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
 
 #ifdef MS_WINDOWS
     handle = _Py_get_osfhandle(fd);
diff --git a/Python/legacy_tracing.c b/Python/legacy_tracing.c
index 45af275f1f6dce..97634f9183c7d5 100644
--- a/Python/legacy_tracing.c
+++ b/Python/legacy_tracing.c
@@ -491,8 +491,8 @@ int
 _PyEval_SetProfile(PyThreadState *tstate, Py_tracefunc func, PyObject *arg)
 {
     assert(is_tstate_valid(tstate));
-    /* The caller must hold the GIL */
-    assert(PyGILState_Check());
+    /* The caller must hold a thread state */
+    _Py_AssertHoldsTstate();
 
     /* Call _PySys_Audit() in the context of 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)
 {
     assert(is_tstate_valid(tstate));
-    /* The caller must hold the GIL */
-    assert(PyGILState_Check());
+    /* The caller must hold a thread state */
+    _Py_AssertHoldsTstate();
 
     /* Call _PySys_Audit() in the context of the current thread state,
        even if tstate is not the current thread state. */
diff --git a/Python/pystate.c b/Python/pystate.c
index c546b7c3a9f10e..52703b048d6022 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -2897,7 +2897,6 @@ _PyInterpreterState_GetConfigCopy(PyConfig *config)
 const PyConfig*
 _Py_GetConfig(void)
 {
-    assert(PyGILState_Check());
     PyThreadState *tstate = current_fast_get();
     _Py_EnsureTstateNotNULL(tstate);
     return _PyInterpreterState_GetConfig(tstate->interp);
diff --git a/Python/pytime.c b/Python/pytime.c
index 2b37cd991ef4e4..c039fc98ce4bde 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -1,5 +1,6 @@
 #include "Python.h"
 #include "pycore_time.h"          // PyTime_t
+#include "pycore_pystate.h"       // _Py_AssertHoldsTstate()
 
 #include <time.h>                 // gmtime_r()
 #ifdef HAVE_SYS_TIME_H
@@ -897,14 +898,14 @@ _PyTime_AsTimespec(PyTime_t t, struct timespec *ts)
 #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
 py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
 {
     assert(info == NULL || raise_exc);
     if (raise_exc) {
-        // raise_exc requires to hold the GIL
-        assert(PyGILState_Check());
+        // raise_exc requires to hold a thread state
+        _Py_AssertHoldsTstate();
     }
 
 #ifdef MS_WINDOWS
@@ -1142,14 +1143,14 @@ py_mach_timebase_info(_PyTimeFraction *base, int 
raise_exc)
 #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
 py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
 {
     assert(info == NULL || raise_exc);
     if (raise_exc) {
-        // raise_exc requires to hold the GIL
-        assert(PyGILState_Check());
+        // raise_exc requires to hold a thread state
+        _Py_AssertHoldsTstate();
     }
 
 #if defined(MS_WINDOWS)
diff --git a/Python/tracemalloc.c b/Python/tracemalloc.c
index 919c564ee72967..a9f45e5ead1a11 100644
--- a/Python/tracemalloc.c
+++ b/Python/tracemalloc.c
@@ -367,7 +367,7 @@ traceback_new(void)
     traceback_t *traceback;
     _Py_hashtable_entry_t *entry;
 
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
 
     /* get frames */
     traceback = tracemalloc_traceback;
@@ -749,7 +749,7 @@ static void
 tracemalloc_clear_traces_unlocked(void)
 {
     // Clearing tracemalloc_filenames requires the GIL to call Py_DECREF()
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
 
     set_reentrant(1);
 
@@ -1302,7 +1302,7 @@ PyTraceMalloc_Untrack(unsigned int domain, uintptr_t ptr)
 void
 _PyTraceMalloc_Fini(void)
 {
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
     tracemalloc_deinit();
 }
 
@@ -1323,7 +1323,7 @@ _PyTraceMalloc_TraceRef(PyObject *op, PyRefTracerEvent 
event,
         return 0;
     }
 
-    assert(PyGILState_Check());
+    _Py_AssertHoldsTstate();
     TABLES_LOCK();
 
     if (!tracemalloc_config.tracing) {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to