mirror of
https://github.com/python/cpython.git
synced 2025-07-08 03:45:36 +00:00

Some checks are pending
Tests / Change detection (push) Waiting to run
Tests / (push) Blocked by required conditions
Tests / Windows MSI (push) Blocked by required conditions
Tests / WASI (push) Blocked by required conditions
Tests / Hypothesis tests on Ubuntu (push) Blocked by required conditions
Tests / Check if the ABI has changed (push) Blocked by required conditions
Tests / Docs (push) Blocked by required conditions
Tests / Check if Autoconf files are up to date (push) Blocked by required conditions
Tests / Check if generated files are up to date (push) Blocked by required conditions
Tests / Ubuntu SSL tests with OpenSSL (push) Blocked by required conditions
Tests / Address sanitizer (push) Blocked by required conditions
Tests / Cross build Linux (push) Blocked by required conditions
Tests / CIFuzz (push) Blocked by required conditions
Tests / All required checks pass (push) Blocked by required conditions
Lint / lint (push) Waiting to run
PEP-734 has been accepted (for 3.14).
(FTR, I'm opposed to putting this under the concurrent package, but
doing so is the SC condition under which the module can land in 3.14.)
(cherry picked from commit 62143736b
, AKA gh-133958)
206 lines
6 KiB
C
206 lines
6 KiB
C
|
|
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 = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
.tp_name = "concurrent.interpreters.InterpreterError",
|
|
.tp_doc = PyDoc_STR("A cross-interpreter operation failed"),
|
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
|
|
//.tp_traverse = ((PyTypeObject *)PyExc_Exception)->tp_traverse,
|
|
//.tp_clear = ((PyTypeObject *)PyExc_Exception)->tp_clear,
|
|
//.tp_base = (PyTypeObject *)PyExc_Exception,
|
|
};
|
|
PyObject *PyExc_InterpreterError = (PyObject *)&_PyExc_InterpreterError;
|
|
|
|
/* InterpreterNotFoundError extends InterpreterError */
|
|
|
|
static PyTypeObject _PyExc_InterpreterNotFoundError = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
.tp_name = "concurrent.interpreters.InterpreterNotFoundError",
|
|
.tp_doc = PyDoc_STR("An interpreter was not found"),
|
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
|
|
//.tp_traverse = ((PyTypeObject *)PyExc_Exception)->tp_traverse,
|
|
//.tp_clear = ((PyTypeObject *)PyExc_Exception)->tp_clear,
|
|
.tp_base = &_PyExc_InterpreterError,
|
|
};
|
|
PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError;
|
|
|
|
/* NotShareableError extends TypeError */
|
|
|
|
static int
|
|
_init_notshareableerror(exceptions_t *state)
|
|
{
|
|
const char *name = "concurrent.interpreters.NotShareableError";
|
|
PyObject *base = PyExc_TypeError;
|
|
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_TypeError;
|
|
}
|
|
_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);
|
|
Py_DECREF(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);
|
|
Py_DECREF(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 */
|
|
|
|
static int
|
|
init_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
|
|
{
|
|
assert(state == &_PyXI_GET_STATE(interp)->exceptions);
|
|
PyTypeObject *base = (PyTypeObject *)PyExc_Exception;
|
|
|
|
// PyExc_InterpreterError
|
|
_PyExc_InterpreterError.tp_base = base;
|
|
_PyExc_InterpreterError.tp_traverse = base->tp_traverse;
|
|
_PyExc_InterpreterError.tp_clear = base->tp_clear;
|
|
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterError) < 0) {
|
|
goto error;
|
|
}
|
|
state->PyExc_InterpreterError = (PyObject *)&_PyExc_InterpreterError;
|
|
|
|
// PyExc_InterpreterNotFoundError
|
|
_PyExc_InterpreterNotFoundError.tp_traverse = base->tp_traverse;
|
|
_PyExc_InterpreterNotFoundError.tp_clear = base->tp_clear;
|
|
if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterNotFoundError) < 0) {
|
|
goto error;
|
|
}
|
|
state->PyExc_InterpreterNotFoundError =
|
|
(PyObject *)&_PyExc_InterpreterNotFoundError;
|
|
|
|
return 0;
|
|
|
|
error:
|
|
fini_static_exctypes(state, interp);
|
|
return -1;
|
|
}
|
|
|
|
static void
|
|
fini_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
|
|
{
|
|
assert(state == &_PyXI_GET_STATE(interp)->exceptions);
|
|
if (state->PyExc_InterpreterNotFoundError != NULL) {
|
|
state->PyExc_InterpreterNotFoundError = NULL;
|
|
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterNotFoundError);
|
|
}
|
|
if (state->PyExc_InterpreterError != NULL) {
|
|
state->PyExc_InterpreterError = NULL;
|
|
_PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterError);
|
|
}
|
|
}
|
|
|
|
static int
|
|
init_heap_exctypes(exceptions_t *state)
|
|
{
|
|
if (_init_notshareableerror(state) < 0) {
|
|
goto error;
|
|
}
|
|
return 0;
|
|
|
|
error:
|
|
fini_heap_exctypes(state);
|
|
return -1;
|
|
}
|
|
|
|
static void
|
|
fini_heap_exctypes(exceptions_t *state)
|
|
{
|
|
_fini_notshareableerror(state);
|
|
}
|