From 4c6955e2b0ccf88c705f8d1fac685a8e65f9699e Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Fri, 16 Feb 2018 18:53:40 -0700 Subject: bpo-32604: Clean up created subinterpreters before runtime finalization. (gh-5709) --- Python/pystate.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) (limited to 'Python/pystate.c') diff --git a/Python/pystate.c b/Python/pystate.c index 8dbda73de7..8cbf1fa10a 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -125,7 +125,8 @@ PyInterpreterState_New(void) return NULL; } - + interp->id_refcount = -1; + interp->id_mutex = NULL; interp->modules = NULL; interp->modules_by_index = NULL; interp->sysdict = NULL; @@ -247,6 +248,9 @@ PyInterpreterState_Delete(PyInterpreterState *interp) Py_FatalError("PyInterpreterState_Delete: remaining subinterpreters"); } HEAD_UNLOCK(); + if (interp->id_mutex != NULL) { + PyThread_free_lock(interp->id_mutex); + } PyMem_RawFree(interp); } @@ -284,6 +288,58 @@ error: return NULL; } + +int +_PyInterpreterState_IDInitref(PyInterpreterState *interp) +{ + if (interp->id_mutex != NULL) { + return 0; + } + interp->id_mutex = PyThread_allocate_lock(); + if (interp->id_mutex == NULL) { + PyErr_SetString(PyExc_RuntimeError, + "failed to create init interpreter ID mutex"); + return -1; + } + interp->id_refcount = 0; + return 0; +} + + +void +_PyInterpreterState_IDIncref(PyInterpreterState *interp) +{ + if (interp->id_mutex == NULL) { + return; + } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); + interp->id_refcount += 1; + PyThread_release_lock(interp->id_mutex); +} + + +void +_PyInterpreterState_IDDecref(PyInterpreterState *interp) +{ + if (interp->id_mutex == NULL) { + return; + } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); + assert(interp->id_refcount != 0); + interp->id_refcount -= 1; + int64_t refcount = interp->id_refcount; + PyThread_release_lock(interp->id_mutex); + + if (refcount == 0) { + PyThreadState *tstate, *save_tstate; + tstate = PyInterpreterState_ThreadHead(interp); + save_tstate = PyThreadState_Swap(tstate); + Py_EndInterpreter(tstate); + PyThreadState_Swap(save_tstate); + } +} + + /* Default implementation for _PyThreadState_GetFrame */ static struct _frame * threadstate_getframe(PyThreadState *self) -- cgit v1.2.1