diff --git a/Include/ceval.h b/Include/ceval.h index 62c6489ed1..3bae89ae62 100644 --- a/Include/ceval.h +++ b/Include/ceval.h @@ -138,12 +138,20 @@ Py_DEPRECATED(3.2) PyAPI_FUNC(void) PyEval_AcquireLock(void); PyAPI_FUNC(void) PyEval_AcquireThread(PyThreadState *tstate); PyAPI_FUNC(void) PyEval_ReleaseThread(PyThreadState *tstate); +#define Py_BLOCK_THREADS \ + if (_wrapper.ts == NULL) PyThread_exit_thread(); \ + PyEval_RestoreThread(_wrapper.ts); +#define Py_UNBLOCK_THREADS \ + _ts = PyThreadState_GET(); \ + _ts->wrapper = &_wrapper; \ + _wrapper.ts = _ts; \ + (void)PyEval_SaveThread(); #define Py_BEGIN_ALLOW_THREADS { \ - PyThreadState *_save; \ - _save = PyEval_SaveThread(); -#define Py_BLOCK_THREADS PyEval_RestoreThread(_save); -#define Py_UNBLOCK_THREADS _save = PyEval_SaveThread(); -#define Py_END_ALLOW_THREADS PyEval_RestoreThread(_save); \ + PyThreadStateWrapper _wrapper; \ + PyThreadState *_ts; \ + Py_UNBLOCK_THREADS +#define Py_END_ALLOW_THREADS \ + Py_BLOCK_THREADS \ } /* Masks and values used by FORMAT_VALUE opcode. */ diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index 6c8d2ae041..61c714ea42 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -135,10 +135,20 @@ struct _ts { /* Unique thread state id. */ uint64_t id; + /* (Optional) wrapper that will survive this thread state being freed, used + * by daemon threads that wake up after interpreter finalization. + */ + struct _ts_wrapper *wrapper; + /* XXX signal handlers should also be here */ }; +// The PyThreadStateWrapper typedef is in Include/pystate.h. +struct _ts_wrapper { + PyThreadState *ts; +}; + /* Get the current interpreter state. Issue a fatal error if there no current Python thread state or no current diff --git a/Include/pystate.h b/Include/pystate.h index 1cb2305696..413e1dc4da 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -17,10 +17,12 @@ removed (with effort). */ and PyInterpreterState */ struct _frame; struct _ts; +struct _ts_wrapper; struct _is; /* struct _ts is defined in cpython/pystate.h */ typedef struct _ts PyThreadState; +typedef struct _ts_wrapper PyThreadStateWrapper; /* struct _is is defined in internal/pycore_pystate.h */ typedef struct _is PyInterpreterState; diff --git a/Python/pystate.c b/Python/pystate.c index 0a6d035836..56e39470c3 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -826,6 +826,10 @@ tstate_delete_common(PyThreadState *tstate, if (tstate->on_delete != NULL) { tstate->on_delete(tstate->on_delete_data); } + if (tstate->wrapper != NULL) { + assert(tstate->wrapper->ts == tstate); + tstate->wrapper->ts = NULL; + } PyMem_RawFree(tstate); if (gilstate->autoInterpreterState &&