summaryrefslogtreecommitdiffstats
path: root/Python/pystate.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/pystate.c')
-rw-r--r--Python/pystate.c68
1 files changed, 38 insertions, 30 deletions
diff --git a/Python/pystate.c b/Python/pystate.c
index 2b7db0e..a9f3389 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -218,6 +218,13 @@ PyInterpreterState_New(void)
return NULL;
}
+ interp->ceval.pending.lock = PyThread_allocate_lock();
+ if (interp->ceval.pending.lock == NULL) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "failed to create interpreter ceval pending mutex");
+ return NULL;
+ }
+
interp->eval_frame = _PyEval_EvalFrameDefault;
#ifdef HAVE_DLOPEN
#if HAVE_DECL_RTLD_NOW
@@ -345,6 +352,10 @@ PyInterpreterState_Delete(PyInterpreterState *interp)
if (interp->id_mutex != NULL) {
PyThread_free_lock(interp->id_mutex);
}
+ if (interp->ceval.pending.lock != NULL) {
+ PyThread_free_lock(interp->ceval.pending.lock);
+ interp->ceval.pending.lock = NULL;
+ }
PyMem_RawFree(interp);
}
@@ -1014,7 +1025,7 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc)
p->async_exc = exc;
HEAD_UNLOCK(runtime);
Py_XDECREF(old_exc);
- _PyEval_SignalAsyncExc(&runtime->ceval);
+ _PyEval_SignalAsyncExc(&runtime->ceval, &interp->ceval);
return 1;
}
}
@@ -1444,7 +1455,7 @@ _PyObject_GetCrossInterpreterData(PyObject *obj, _PyCrossInterpreterData *data)
return 0;
}
-static void
+static int
_release_xidata(void *arg)
{
_PyCrossInterpreterData *data = (_PyCrossInterpreterData *)arg;
@@ -1452,42 +1463,21 @@ _release_xidata(void *arg)
data->free(data->data);
}
Py_XDECREF(data->obj);
-}
-
-static void
-_call_in_interpreter(struct _gilstate_runtime_state *gilstate,
- PyInterpreterState *interp,
- void (*func)(void *), void *arg)
-{
- /* We would use Py_AddPendingCall() if it weren't specific to the
- * main interpreter (see bpo-33608). In the meantime we take a
- * naive approach.
- */
- PyThreadState *save_tstate = NULL;
- if (interp != _PyRuntimeGILState_GetThreadState(gilstate)->interp) {
- // XXX Using the "head" thread isn't strictly correct.
- PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
- // XXX Possible GILState issues?
- save_tstate = _PyThreadState_Swap(gilstate, tstate);
- }
-
- func(arg);
-
- // Switch back.
- if (save_tstate != NULL) {
- _PyThreadState_Swap(gilstate, save_tstate);
- }
+ PyMem_Free(data);
+ return 0;
}
void
_PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
{
+ _PyRuntimeState *runtime = &_PyRuntime;
+
if (data->data == NULL && data->obj == NULL) {
// Nothing to release!
return;
}
- // Switch to the original interpreter.
+ // Get the original interpreter.
PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interp);
if (interp == NULL) {
// The intepreter was already destroyed.
@@ -1496,10 +1486,28 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data)
}
return;
}
+ // XXX There's an ever-so-slight race here...
+ if (interp->finalizing) {
+ // XXX Someone leaked some memory...
+ return;
+ }
// "Release" the data and/or the object.
- struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate;
- _call_in_interpreter(gilstate, interp, _release_xidata, data);
+ _PyCrossInterpreterData *copied = PyMem_Malloc(sizeof(_PyCrossInterpreterData));
+ if (copied == NULL) {
+ PyErr_SetString(PyExc_MemoryError,
+ "Not enough memory to preserve cross-interpreter data");
+ PyErr_Print();
+ return;
+ }
+ memcpy(copied, data, sizeof(_PyCrossInterpreterData));
+ PyThreadState *tstate = _PyRuntimeState_GetThreadState(runtime);
+ int res = _PyEval_AddPendingCall(tstate,
+ &runtime->ceval, &interp->ceval,
+ 0, _release_xidata, copied);
+ if (res != 0) {
+ // XXX Queue full or couldn't get lock. Try again somehow?
+ }
}
PyObject *