mirror of
https://github.com/python/cpython.git
synced 2025-10-21 06:02:21 +00:00
bpo-40226: PyInterpreterState_Delete() deletes pending calls (GH-19436)
PyInterpreterState_New() is now responsible to create pending calls, PyInterpreterState_Delete() now deletes pending calls. * Rename _PyEval_InitThreads() to _PyEval_InitGIL() and rename _PyEval_InitGIL() to _PyEval_FiniGIL(). * _PyEval_InitState() and PyEval_FiniState() now create and delete pending calls. _PyEval_InitState() now returns -1 on memory allocation failure. * Add init_interp_create_gil() helper function: code shared by Py_NewInterpreter() and Py_InitializeFromConfig(). * init_interp_create_gil() now also calls _PyEval_FiniGIL(), _PyEval_InitGIL() and _PyGILState_Init() in subinterpreters, but these functions now do nothing when called from a subinterpreter.
This commit is contained in:
parent
ac2cfe6631
commit
dda5d6e071
4 changed files with 117 additions and 60 deletions
|
@ -275,56 +275,54 @@ PyEval_ThreadsInitialized(void)
|
|||
}
|
||||
|
||||
PyStatus
|
||||
_PyEval_InitThreads(PyThreadState *tstate)
|
||||
_PyEval_InitGIL(PyThreadState *tstate)
|
||||
{
|
||||
assert(is_tstate_valid(tstate));
|
||||
|
||||
if (_Py_IsMainInterpreter(tstate)) {
|
||||
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
|
||||
if (gil_created(gil)) {
|
||||
return _PyStatus_OK();
|
||||
}
|
||||
|
||||
PyThread_init_thread();
|
||||
create_gil(gil);
|
||||
|
||||
take_gil(tstate);
|
||||
if (!_Py_IsMainInterpreter(tstate)) {
|
||||
/* Currently, the GIL is shared by all interpreters,
|
||||
and only the main interpreter is responsible to create
|
||||
and destroy it. */
|
||||
return _PyStatus_OK();
|
||||
}
|
||||
|
||||
struct _pending_calls *pending = &tstate->interp->ceval.pending;
|
||||
assert(pending->lock == NULL);
|
||||
pending->lock = PyThread_allocate_lock();
|
||||
if (pending->lock == NULL) {
|
||||
return _PyStatus_NO_MEMORY();
|
||||
}
|
||||
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
|
||||
assert(!gil_created(gil));
|
||||
|
||||
PyThread_init_thread();
|
||||
create_gil(gil);
|
||||
|
||||
take_gil(tstate);
|
||||
|
||||
assert(gil_created(gil));
|
||||
return _PyStatus_OK();
|
||||
}
|
||||
|
||||
void
|
||||
_PyEval_FiniGIL(PyThreadState *tstate)
|
||||
{
|
||||
if (!_Py_IsMainInterpreter(tstate)) {
|
||||
/* Currently, the GIL is shared by all interpreters,
|
||||
and only the main interpreter is responsible to create
|
||||
and destroy it. */
|
||||
return;
|
||||
}
|
||||
|
||||
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
|
||||
if (!gil_created(gil)) {
|
||||
/* First Py_InitializeFromConfig() call: the GIL doesn't exist
|
||||
yet: do nothing. */
|
||||
return;
|
||||
}
|
||||
|
||||
destroy_gil(gil);
|
||||
assert(!gil_created(gil));
|
||||
}
|
||||
|
||||
void
|
||||
PyEval_InitThreads(void)
|
||||
{
|
||||
/* Do nothing: kept for backward compatibility */
|
||||
}
|
||||
|
||||
void
|
||||
_PyEval_FiniThreads(PyThreadState *tstate)
|
||||
{
|
||||
struct _gil_runtime_state *gil = &tstate->interp->runtime->ceval.gil;
|
||||
if (!gil_created(gil)) {
|
||||
return;
|
||||
}
|
||||
|
||||
destroy_gil(gil);
|
||||
assert(!gil_created(gil));
|
||||
|
||||
struct _pending_calls *pending = &tstate->interp->ceval.pending;
|
||||
if (pending->lock != NULL) {
|
||||
PyThread_free_lock(pending->lock);
|
||||
pending->lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_PyEval_Fini(void)
|
||||
{
|
||||
|
@ -544,6 +542,10 @@ _PyEval_AddPendingCall(PyThreadState *tstate,
|
|||
{
|
||||
struct _pending_calls *pending = &tstate->interp->ceval.pending;
|
||||
|
||||
/* Ensure that _PyEval_InitPendingCalls() was called
|
||||
and that _PyEval_FiniPendingCalls() is not called yet. */
|
||||
assert(pending->lock != NULL);
|
||||
|
||||
PyThread_acquire_lock(pending->lock, WAIT_LOCK);
|
||||
if (pending->finishing) {
|
||||
PyThread_release_lock(pending->lock);
|
||||
|
@ -721,10 +723,27 @@ _PyEval_InitRuntimeState(struct _ceval_runtime_state *ceval)
|
|||
_gil_initialize(&ceval->gil);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
_PyEval_InitState(struct _ceval_state *ceval)
|
||||
{
|
||||
/* PyInterpreterState_New() initializes ceval to zero */
|
||||
struct _pending_calls *pending = &ceval->pending;
|
||||
assert(pending->lock == NULL);
|
||||
|
||||
pending->lock = PyThread_allocate_lock();
|
||||
if (pending->lock == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_PyEval_FiniState(struct _ceval_state *ceval)
|
||||
{
|
||||
struct _pending_calls *pending = &ceval->pending;
|
||||
if (pending->lock != NULL) {
|
||||
PyThread_free_lock(pending->lock);
|
||||
pending->lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue