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.
This commit is contained in:
Eric Snow 2018-02-20 16:30:17 -07:00 committed by GitHub
parent 80d20b918b
commit f53d9f2778
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 77 additions and 14 deletions

View file

@ -1759,8 +1759,13 @@ _run_script_in_interpreter(PyInterpreterState *interp, const char *codestr,
}
// Switch to interpreter.
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);
}
// Run the script.
_sharedexception *exc = NULL;
@ -2079,9 +2084,9 @@ interp_create(PyObject *self, PyObject *args)
}
// Create and initialize the new interpreter.
PyThreadState *tstate, *save_tstate;
save_tstate = PyThreadState_Swap(NULL);
tstate = Py_NewInterpreter();
PyThreadState *save_tstate = PyThreadState_Swap(NULL);
// XXX Possible GILState issues?
PyThreadState *tstate = Py_NewInterpreter();
PyThreadState_Swap(save_tstate);
if (tstate == NULL) {
/* Since no new thread state was created, there is no exception to
@ -2096,6 +2101,7 @@ interp_create(PyObject *self, PyObject *args)
return _get_id(tstate->interp);
error:
// XXX Possible GILState issues?
save_tstate = PyThreadState_Swap(tstate);
Py_EndInterpreter(tstate);
PyThreadState_Swap(save_tstate);
@ -2146,9 +2152,9 @@ interp_destroy(PyObject *self, PyObject *args)
// Destroy the interpreter.
//PyInterpreterState_Delete(interp);
PyThreadState *tstate, *save_tstate;
tstate = PyInterpreterState_ThreadHead(interp);
save_tstate = PyThreadState_Swap(tstate);
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
// XXX Possible GILState issues?
PyThreadState *save_tstate = PyThreadState_Swap(tstate);
Py_EndInterpreter(tstate);
PyThreadState_Swap(save_tstate);