diff options
Diffstat (limited to 'Modules/_xxsubinterpretersmodule.c')
-rw-r--r-- | Modules/_xxsubinterpretersmodule.c | 90 |
1 files changed, 47 insertions, 43 deletions
diff --git a/Modules/_xxsubinterpretersmodule.c b/Modules/_xxsubinterpretersmodule.c index 5d4f1b9..c0958c6 100644 --- a/Modules/_xxsubinterpretersmodule.c +++ b/Modules/_xxsubinterpretersmodule.c @@ -2,7 +2,14 @@ /* interpreters module */ /* low-level access to interpreter primitives */ +#ifndef Py_BUILD_CORE_BUILTIN +# define Py_BUILD_CORE_MODULE 1 +#endif + #include "Python.h" +#include "pycore_initconfig.h" // _PyErr_SetFromPyStatus() +#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1() +#include "pycore_pystate.h" // _PyInterpreterState_SetRunningMain() #include "interpreteridobject.h" @@ -353,41 +360,14 @@ exceptions_init(PyObject *mod) } static int -_is_running(PyInterpreterState *interp) -{ - PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); - if (PyThreadState_Next(tstate) != NULL) { - PyErr_SetString(PyExc_RuntimeError, - "interpreter has more than one thread"); - return -1; - } - - assert(!PyErr_Occurred()); - struct _PyInterpreterFrame *frame = tstate->cframe->current_frame; - if (frame == NULL) { - return 0; - } - return 1; -} - -static int -_ensure_not_running(PyInterpreterState *interp) +_run_script(PyInterpreterState *interp, const char *codestr, + _sharedns *shared, _sharedexception *sharedexc) { - int is_running = _is_running(interp); - if (is_running < 0) { + if (_PyInterpreterState_SetRunningMain(interp) < 0) { + // We skip going through the shared exception. return -1; } - if (is_running) { - PyErr_Format(PyExc_RuntimeError, "interpreter already running"); - return -1; - } - return 0; -} -static int -_run_script(PyInterpreterState *interp, const char *codestr, - _sharedns *shared, _sharedexception *sharedexc) -{ PyObject *excval = NULL; PyObject *main_mod = _PyInterpreterState_GetMainModule(interp); if (main_mod == NULL) { @@ -417,6 +397,7 @@ _run_script(PyInterpreterState *interp, const char *codestr, else { Py_DECREF(result); // We throw away the result. } + _PyInterpreterState_SetNotRunningMain(interp); *sharedexc = no_exception; return 0; @@ -432,6 +413,7 @@ error: } Py_XDECREF(excval); assert(!PyErr_Occurred()); + _PyInterpreterState_SetNotRunningMain(interp); return -1; } @@ -439,9 +421,6 @@ static int _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp, const char *codestr, PyObject *shareables) { - if (_ensure_not_running(interp) < 0) { - return -1; - } module_state *state = get_module_state(mod); _sharedns *shared = _get_shared_ns(shareables); @@ -452,8 +431,26 @@ _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp, // Switch to interpreter. PyThreadState *save_tstate = NULL; if (interp != PyInterpreterState_Get()) { - // XXX Using the "head" thread isn't strictly correct. + // XXX gh-109860: Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + assert(tstate != NULL); + // Hack (until gh-109860): The interpreter's initial thread state + // is least likely to break. + while(tstate->next != NULL) { + tstate = tstate->next; + } + // We must do this check before switching interpreters, so any + // exception gets raised in the right one. + // XXX gh-109860: Drop this redundant check once we stop + // re-using tstates that might already be in use. + if (_PyInterpreterState_IsRunningMain(interp)) { + PyErr_SetString(PyExc_RuntimeError, + "interpreter already running"); + if (shared != NULL) { + _sharedns_free(shared); + } + return -1; + } // XXX Possible GILState issues? save_tstate = PyThreadState_Swap(tstate); } @@ -473,8 +470,10 @@ _run_script_in_interpreter(PyObject *mod, PyInterpreterState *interp, _sharedexception_apply(&exc, state->RunFailedError); } else if (result != 0) { - // We were unable to allocate a shared exception. - PyErr_NoMemory(); + if (!PyErr_Occurred()) { + // We were unable to allocate a shared exception. + PyErr_NoMemory(); + } } if (shared != NULL) { @@ -569,12 +568,20 @@ interp_destroy(PyObject *self, PyObject *args, PyObject *kwds) // Ensure the interpreter isn't running. /* XXX We *could* support destroying a running interpreter but aren't going to worry about it for now. */ - if (_ensure_not_running(interp) < 0) { + if (_PyInterpreterState_IsRunningMain(interp)) { + PyErr_Format(PyExc_RuntimeError, "interpreter running"); return NULL; } // Destroy the interpreter. + // XXX gh-109860: Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); + assert(tstate != NULL); + // Hack (until gh-109860): The interpreter's initial thread state + // is least likely to break. + while(tstate->next != NULL) { + tstate = tstate->next; + } // XXX Possible GILState issues? PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); @@ -743,11 +750,7 @@ interp_is_running(PyObject *self, PyObject *args, PyObject *kwds) if (interp == NULL) { return NULL; } - int is_running = _is_running(interp); - if (is_running < 0) { - return NULL; - } - if (is_running) { + if (_PyInterpreterState_IsRunningMain(interp)) { Py_RETURN_TRUE; } Py_RETURN_FALSE; @@ -758,6 +761,7 @@ PyDoc_STRVAR(is_running_doc, \n\ Return whether or not the identified interpreter is running."); + static PyMethodDef module_functions[] = { {"create", _PyCFunction_CAST(interp_create), METH_VARARGS | METH_KEYWORDS, create_doc}, |