diff options
Diffstat (limited to 'Modules/_interpretersmodule.c')
-rw-r--r-- | Modules/_interpretersmodule.c | 90 |
1 files changed, 52 insertions, 38 deletions
diff --git a/Modules/_interpretersmodule.c b/Modules/_interpretersmodule.c index 037e9544543..fdfb3e6dd34 100644 --- a/Modules/_interpretersmodule.c +++ b/Modules/_interpretersmodule.c @@ -80,21 +80,11 @@ is_notshareable_raised(PyThreadState *tstate) } static void -unwrap_not_shareable(PyThreadState *tstate) +unwrap_not_shareable(PyThreadState *tstate, _PyXI_failure *failure) { - if (!is_notshareable_raised(tstate)) { - return; - } - PyObject *exc = _PyErr_GetRaisedException(tstate); - PyObject *cause = PyException_GetCause(exc); - if (cause != NULL) { - Py_DECREF(exc); - exc = cause; + if (_PyXI_UnwrapNotShareableError(tstate, failure) < 0) { + _PyErr_Clear(tstate); } - else { - assert(PyException_GetContext(exc) == NULL); - } - _PyErr_SetRaisedException(tstate, exc); } @@ -532,13 +522,30 @@ _interp_call_pack(PyThreadState *tstate, struct interp_call *call, return 0; } +static void +wrap_notshareable(PyThreadState *tstate, const char *label) +{ + if (!is_notshareable_raised(tstate)) { + return; + } + assert(label != NULL && strlen(label) > 0); + PyObject *cause = _PyErr_GetRaisedException(tstate); + _PyXIData_FormatNotShareableError(tstate, "%s not shareable", label); + PyObject *exc = _PyErr_GetRaisedException(tstate); + PyException_SetCause(exc, cause); + _PyErr_SetRaisedException(tstate, exc); +} + static int _interp_call_unpack(struct interp_call *call, PyObject **p_func, PyObject **p_args, PyObject **p_kwargs) { + PyThreadState *tstate = PyThreadState_Get(); + // Unpack the func. PyObject *func = _PyXIData_NewObject(call->func); if (func == NULL) { + wrap_notshareable(tstate, "func"); return -1; } // Unpack the args. @@ -553,6 +560,7 @@ _interp_call_unpack(struct interp_call *call, else { args = _PyXIData_NewObject(call->args); if (args == NULL) { + wrap_notshareable(tstate, "args"); Py_DECREF(func); return -1; } @@ -563,6 +571,7 @@ _interp_call_unpack(struct interp_call *call, if (call->kwargs != NULL) { kwargs = _PyXIData_NewObject(call->kwargs); if (kwargs == NULL) { + wrap_notshareable(tstate, "kwargs"); Py_DECREF(func); Py_DECREF(args); return -1; @@ -577,7 +586,7 @@ _interp_call_unpack(struct interp_call *call, static int _make_call(struct interp_call *call, - PyObject **p_result, _PyXI_errcode *p_errcode) + PyObject **p_result, _PyXI_failure *failure) { assert(call != NULL && call->func != NULL); PyThreadState *tstate = _PyThreadState_GET(); @@ -588,12 +597,10 @@ _make_call(struct interp_call *call, assert(func == NULL); assert(args == NULL); assert(kwargs == NULL); - *p_errcode = is_notshareable_raised(tstate) - ? _PyXI_ERR_NOT_SHAREABLE - : _PyXI_ERR_OTHER; + _PyXI_InitFailure(failure, _PyXI_ERR_OTHER, NULL); + unwrap_not_shareable(tstate, failure); return -1; } - *p_errcode = _PyXI_ERR_NO_ERROR; // Make the call. PyObject *resobj = PyObject_Call(func, args, kwargs); @@ -608,17 +615,17 @@ _make_call(struct interp_call *call, } static int -_run_script(_PyXIData_t *script, PyObject *ns, _PyXI_errcode *p_errcode) +_run_script(_PyXIData_t *script, PyObject *ns, _PyXI_failure *failure) { PyObject *code = _PyXIData_NewObject(script); if (code == NULL) { - *p_errcode = _PyXI_ERR_NOT_SHAREABLE; + _PyXI_InitFailure(failure, _PyXI_ERR_NOT_SHAREABLE, NULL); return -1; } PyObject *result = PyEval_EvalCode(code, ns, ns); Py_DECREF(code); if (result == NULL) { - *p_errcode = _PyXI_ERR_UNCAUGHT_EXCEPTION; + _PyXI_InitFailure(failure, _PyXI_ERR_UNCAUGHT_EXCEPTION, NULL); return -1; } assert(result == Py_None); @@ -644,8 +651,14 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp, PyObject *shareables, struct run_result *runres) { assert(!_PyErr_Occurred(tstate)); + int res = -1; + _PyXI_failure *failure = _PyXI_NewFailure(); + if (failure == NULL) { + return -1; + } _PyXI_session *session = _PyXI_NewSession(); if (session == NULL) { + _PyXI_FreeFailure(failure); return -1; } _PyXI_session_result result = {0}; @@ -655,43 +668,44 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp, // If an error occured at this step, it means that interp // was not prepared and switched. _PyXI_FreeSession(session); + _PyXI_FreeFailure(failure); assert(result.excinfo == NULL); return -1; } // Run in the interpreter. - int res = -1; - _PyXI_errcode errcode = _PyXI_ERR_NO_ERROR; if (script != NULL) { assert(call == NULL); - PyObject *mainns = _PyXI_GetMainNamespace(session, &errcode); + PyObject *mainns = _PyXI_GetMainNamespace(session, failure); if (mainns == NULL) { goto finally; } - res = _run_script(script, mainns, &errcode); + res = _run_script(script, mainns, failure); } else { assert(call != NULL); PyObject *resobj; - res = _make_call(call, &resobj, &errcode); + res = _make_call(call, &resobj, failure); if (res == 0) { - res = _PyXI_Preserve(session, "resobj", resobj, &errcode); + res = _PyXI_Preserve(session, "resobj", resobj, failure); Py_DECREF(resobj); if (res < 0) { goto finally; } } } - int exitres; finally: // Clean up and switch back. - exitres = _PyXI_Exit(session, errcode, &result); + (void)res; + int exitres = _PyXI_Exit(session, failure, &result); assert(res == 0 || exitres != 0); _PyXI_FreeSession(session); + _PyXI_FreeFailure(failure); res = exitres; if (_PyErr_Occurred(tstate)) { + // It's a directly propagated exception. assert(res < 0); } else if (res < 0) { @@ -1064,7 +1078,7 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs) // Clean up and switch back. assert(!PyErr_Occurred()); - int res = _PyXI_Exit(session, _PyXI_ERR_NO_ERROR, NULL); + int res = _PyXI_Exit(session, NULL, NULL); _PyXI_FreeSession(session); assert(res == 0); if (res < 0) { @@ -1124,7 +1138,7 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds) // global variables. They will be resolved against __main__. _PyXIData_t xidata = {0}; if (_PyCode_GetScriptXIData(tstate, code, &xidata) < 0) { - unwrap_not_shareable(tstate); + unwrap_not_shareable(tstate, NULL); return NULL; } @@ -1188,7 +1202,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) _PyXIData_t xidata = {0}; if (_PyCode_GetScriptXIData(tstate, script, &xidata) < 0) { - unwrap_not_shareable(tstate); + unwrap_not_shareable(tstate, NULL); return NULL; } @@ -1251,7 +1265,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds) _PyXIData_t xidata = {0}; if (_PyCode_GetScriptXIData(tstate, code, &xidata) < 0) { - unwrap_not_shareable(tstate); + unwrap_not_shareable(tstate, NULL); return NULL; } @@ -1542,16 +1556,16 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds) } PyObject *captured = NULL; - _PyXI_excinfo info = {0}; - if (_PyXI_InitExcInfo(&info, exc) < 0) { + _PyXI_excinfo *info = _PyXI_NewExcInfo(exc); + if (info == NULL) { goto finally; } - captured = _PyXI_ExcInfoAsObject(&info); + captured = _PyXI_ExcInfoAsObject(info); if (captured == NULL) { goto finally; } - PyObject *formatted = _PyXI_FormatExcInfo(&info); + PyObject *formatted = _PyXI_FormatExcInfo(info); if (formatted == NULL) { Py_CLEAR(captured); goto finally; @@ -1564,7 +1578,7 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds) } finally: - _PyXI_ClearExcInfo(&info); + _PyXI_FreeExcInfo(info); if (exc != exc_arg) { if (PyErr_Occurred()) { PyErr_SetRaisedException(exc); |