From f53d9f2778a87bdd48eb9030f782a4ebf9e7622f Mon Sep 17 00:00:00 2001 From: Eric Snow Date: Tue, 20 Feb 2018 16:30:17 -0700 Subject: bpo-32604: Swap threads only if the interpreter is different. (gh-5778) The CPython runtime assumes that there is a one-to-one relationship (for a given interpreter) between PyThreadState and OS threads. Sending and receiving on a channel in the same interpreter was causing crashes because of this (specifically due to a check in PyThreadState_Swap()). The solution is to not switch threads if the interpreter is the same. --- Python/pystate.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'Python/pystate.c') diff --git a/Python/pystate.c b/Python/pystate.c index 8cbf1fa10a..a87801f569 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -331,9 +331,10 @@ _PyInterpreterState_IDDecref(PyInterpreterState *interp) PyThread_release_lock(interp->id_mutex); if (refcount == 0) { - PyThreadState *tstate, *save_tstate; - tstate = PyInterpreterState_ThreadHead(interp); - save_tstate = PyThreadState_Swap(tstate); + // XXX Using the "head" thread isn't strictly correct. + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + // XXX Possible GILState issues? + PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); } @@ -1213,8 +1214,14 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) } return; } - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - PyThreadState *save_tstate = PyThreadState_Swap(tstate); + + PyThreadState *save_tstate = NULL; + if (interp != PyThreadState_Get()->interp) { + // XXX Using the "head" thread isn't strictly correct. + PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + // XXX Possible GILState issues? + save_tstate = PyThreadState_Swap(tstate); + } // "Release" the data and/or the object. if (data->free != NULL) { @@ -1223,8 +1230,9 @@ _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) Py_XDECREF(data->obj); // Switch back. - if (save_tstate != NULL) + if (save_tstate != NULL) { PyThreadState_Swap(save_tstate); + } } PyObject * -- cgit v1.2.1