diff options
Diffstat (limited to 'Python/crossinterp_exceptions.h')
-rw-r--r-- | Python/crossinterp_exceptions.h | 125 |
1 files changed, 114 insertions, 11 deletions
diff --git a/Python/crossinterp_exceptions.h b/Python/crossinterp_exceptions.h index 3cb45d2..3999364 100644 --- a/Python/crossinterp_exceptions.h +++ b/Python/crossinterp_exceptions.h @@ -1,4 +1,25 @@ +static void +_ensure_current_cause(PyThreadState *tstate, PyObject *cause) +{ + if (cause == NULL) { + return; + } + PyObject *exc = _PyErr_GetRaisedException(tstate); + assert(exc != NULL); + PyObject *ctx = PyException_GetContext(exc); + if (ctx == NULL) { + PyException_SetContext(exc, Py_NewRef(cause)); + } + else { + Py_DECREF(ctx); + } + assert(PyException_GetCause(exc) == NULL); + PyException_SetCause(exc, Py_NewRef(cause)); + _PyErr_SetRaisedException(tstate, exc); +} + + /* InterpreterError extends Exception */ static PyTypeObject _PyExc_InterpreterError = { @@ -25,6 +46,97 @@ static PyTypeObject _PyExc_InterpreterNotFoundError = { }; PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError; +/* NotShareableError extends ValueError */ + +static int +_init_notshareableerror(exceptions_t *state) +{ + const char *name = "interpreters.NotShareableError"; + // XXX Inherit from TypeError. + PyObject *base = PyExc_ValueError; + PyObject *ns = NULL; + PyObject *exctype = PyErr_NewException(name, base, ns); + if (exctype == NULL) { + return -1; + } + state->PyExc_NotShareableError = exctype; + return 0; +} + +static void +_fini_notshareableerror(exceptions_t *state) +{ + Py_CLEAR(state->PyExc_NotShareableError); +} + +static PyObject * +get_notshareableerror_type(PyThreadState *tstate) +{ + _PyXI_state_t *local = _PyXI_GET_STATE(tstate->interp); + if (local == NULL) { + PyErr_Clear(); + return NULL; + } + return local->exceptions.PyExc_NotShareableError; +} + +static void +_ensure_notshareableerror(PyThreadState *tstate, + PyObject *cause, int force, PyObject *msgobj) +{ + PyObject *ctx = _PyErr_GetRaisedException(tstate); + PyObject *exctype = get_notshareableerror_type(tstate); + if (exctype != NULL) { + if (!force && ctx != NULL && Py_TYPE(ctx) == (PyTypeObject *)exctype) { + // A NotShareableError instance is already set. + assert(cause == NULL); + _PyErr_SetRaisedException(tstate, ctx); + } + } + else { + exctype = PyExc_ValueError; + } + _PyErr_SetObject(tstate, exctype, msgobj); + // We have to set the context manually since _PyErr_SetObject() doesn't. + _PyErr_ChainExceptions1Tstate(tstate, ctx); + _ensure_current_cause(tstate, cause); +} + +static void +set_notshareableerror(PyThreadState *tstate, PyObject *cause, int force, const char *msg) +{ + PyObject *msgobj = PyUnicode_FromString(msg); + if (msgobj == NULL) { + assert(_PyErr_Occurred(tstate)); + } + else { + _ensure_notshareableerror(tstate, cause, force, msgobj); + } +} + +static void +format_notshareableerror_v(PyThreadState *tstate, PyObject *cause, int force, + const char *format, va_list vargs) +{ + PyObject *msgobj = PyUnicode_FromFormatV(format, vargs); + if (msgobj == NULL) { + assert(_PyErr_Occurred(tstate)); + } + else { + _ensure_notshareableerror(tstate, cause, force, msgobj); + } +} + +static void +format_notshareableerror(PyThreadState *tstate, PyObject *cause, int force, + const char *format, ...) +{ + va_list vargs; + va_start(vargs, format); + format_notshareableerror_v(tstate, cause, force, format, vargs); + va_end(vargs); +} + /* lifecycle */ @@ -76,18 +188,9 @@ fini_static_exctypes(exceptions_t *state, PyInterpreterState *interp) static int init_heap_exctypes(exceptions_t *state) { - PyObject *exctype; - - /* NotShareableError extends ValueError */ - const char *name = "interpreters.NotShareableError"; - PyObject *base = PyExc_ValueError; - PyObject *ns = NULL; - exctype = PyErr_NewException(name, base, ns); - if (exctype == NULL) { + if (_init_notshareableerror(state) < 0) { goto error; } - state->PyExc_NotShareableError = exctype; - return 0; error: @@ -98,5 +201,5 @@ error: static void fini_heap_exctypes(exceptions_t *state) { - Py_CLEAR(state->PyExc_NotShareableError); + _fini_notshareableerror(state); } |