Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Python/crossinterp_exceptions.h
Line
Count
Source (jump to first uncovered line)
1
2
static void
3
_ensure_current_cause(PyThreadState *tstate, PyObject *cause)
4
0
{
5
0
    if (cause == NULL) {
6
0
        return;
7
0
    }
8
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
9
0
    assert(exc != NULL);
10
0
    assert(PyException_GetCause(exc) == NULL);
11
0
    PyException_SetCause(exc, Py_NewRef(cause));
12
0
    _PyErr_SetRaisedException(tstate, exc);
13
0
}
14
15
16
/* InterpreterError extends Exception */
17
18
static PyTypeObject _PyExc_InterpreterError = {
19
    PyVarObject_HEAD_INIT(NULL, 0)
20
    .tp_name = "concurrent.interpreters.InterpreterError",
21
    .tp_doc = PyDoc_STR("A cross-interpreter operation failed"),
22
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
23
    //.tp_traverse = ((PyTypeObject *)PyExc_Exception)->tp_traverse,
24
    //.tp_clear = ((PyTypeObject *)PyExc_Exception)->tp_clear,
25
    //.tp_base = (PyTypeObject *)PyExc_Exception,
26
};
27
PyObject *PyExc_InterpreterError = (PyObject *)&_PyExc_InterpreterError;
28
29
/* InterpreterNotFoundError extends InterpreterError */
30
31
static PyTypeObject _PyExc_InterpreterNotFoundError = {
32
    PyVarObject_HEAD_INIT(NULL, 0)
33
    .tp_name = "concurrent.interpreters.InterpreterNotFoundError",
34
    .tp_doc = PyDoc_STR("An interpreter was not found"),
35
    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC,
36
    //.tp_traverse = ((PyTypeObject *)PyExc_Exception)->tp_traverse,
37
    //.tp_clear = ((PyTypeObject *)PyExc_Exception)->tp_clear,
38
    .tp_base = &_PyExc_InterpreterError,
39
};
40
PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError;
41
42
/* NotShareableError extends TypeError */
43
44
static int
45
_init_notshareableerror(exceptions_t *state)
46
16
{
47
16
    const char *name = "concurrent.interpreters.NotShareableError";
48
16
    PyObject *base = PyExc_TypeError;
49
16
    PyObject *ns = NULL;
50
16
    PyObject *exctype = PyErr_NewException(name, base, ns);
51
16
    if (exctype == NULL) {
52
0
        return -1;
53
0
    }
54
16
    state->PyExc_NotShareableError = exctype;
55
16
    return 0;
56
16
}
57
58
static void
59
_fini_notshareableerror(exceptions_t *state)
60
0
{
61
0
    Py_CLEAR(state->PyExc_NotShareableError);
62
0
}
63
64
static PyObject *
65
get_notshareableerror_type(PyThreadState *tstate)
66
0
{
67
0
    _PyXI_state_t *local = _PyXI_GET_STATE(tstate->interp);
68
0
    if (local == NULL) {
69
0
        PyErr_Clear();
70
0
        return NULL;
71
0
    }
72
0
    return local->exceptions.PyExc_NotShareableError;
73
0
}
74
75
static void
76
_ensure_notshareableerror(PyThreadState *tstate,
77
                          PyObject *cause, int force, PyObject *msgobj)
78
0
{
79
0
    PyObject *ctx = _PyErr_GetRaisedException(tstate);
80
0
    PyObject *exctype = get_notshareableerror_type(tstate);
81
0
    if (exctype != NULL) {
82
0
        if (!force && ctx != NULL && Py_TYPE(ctx) == (PyTypeObject *)exctype) {
83
            // A NotShareableError instance is already set.
84
0
            assert(cause == NULL);
85
0
            _PyErr_SetRaisedException(tstate, ctx);
86
0
        }
87
0
    }
88
0
    else {
89
0
        exctype = PyExc_TypeError;
90
0
    }
91
0
    _PyErr_SetObject(tstate, exctype, msgobj);
92
    // We have to set the context manually since _PyErr_SetObject() doesn't.
93
0
    _PyErr_ChainExceptions1Tstate(tstate, ctx);
94
0
    _ensure_current_cause(tstate, cause);
95
0
}
96
97
static void
98
set_notshareableerror(PyThreadState *tstate, PyObject *cause, int force, const char *msg)
99
0
{
100
0
    PyObject *msgobj = PyUnicode_FromString(msg);
101
0
    if (msgobj == NULL) {
102
0
        assert(_PyErr_Occurred(tstate));
103
0
    }
104
0
    else {
105
0
        _ensure_notshareableerror(tstate, cause, force, msgobj);
106
0
        Py_DECREF(msgobj);
107
0
    }
108
0
}
109
110
static void
111
format_notshareableerror_v(PyThreadState *tstate, PyObject *cause, int force,
112
                           const char *format, va_list vargs)
113
0
{
114
0
    PyObject *msgobj = PyUnicode_FromFormatV(format, vargs);
115
0
    if (msgobj == NULL) {
116
0
        assert(_PyErr_Occurred(tstate));
117
0
    }
118
0
    else {
119
0
        _ensure_notshareableerror(tstate, cause, force, msgobj);
120
0
        Py_DECREF(msgobj);
121
0
    }
122
0
}
123
124
static void
125
format_notshareableerror(PyThreadState *tstate, PyObject *cause, int force,
126
                         const char *format, ...)
127
0
{
128
0
    va_list vargs;
129
0
    va_start(vargs, format);
130
0
    format_notshareableerror_v(tstate, cause, force, format, vargs);
131
0
    va_end(vargs);
132
0
}
133
134
135
/* lifecycle */
136
137
static int
138
init_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
139
16
{
140
16
    assert(state == &_PyXI_GET_STATE(interp)->exceptions);
141
16
    PyTypeObject *base = (PyTypeObject *)PyExc_Exception;
142
143
    // PyExc_InterpreterError
144
16
    _PyExc_InterpreterError.tp_base = base;
145
16
    _PyExc_InterpreterError.tp_traverse = base->tp_traverse;
146
16
    _PyExc_InterpreterError.tp_clear = base->tp_clear;
147
16
    if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterError) < 0) {
148
0
        goto error;
149
0
    }
150
16
    state->PyExc_InterpreterError = (PyObject *)&_PyExc_InterpreterError;
151
152
    // PyExc_InterpreterNotFoundError
153
16
    _PyExc_InterpreterNotFoundError.tp_traverse = base->tp_traverse;
154
16
    _PyExc_InterpreterNotFoundError.tp_clear = base->tp_clear;
155
16
    if (_PyStaticType_InitBuiltin(interp, &_PyExc_InterpreterNotFoundError) < 0) {
156
0
        goto error;
157
0
    }
158
16
    state->PyExc_InterpreterNotFoundError =
159
16
            (PyObject *)&_PyExc_InterpreterNotFoundError;
160
161
16
    return 0;
162
163
0
error:
164
0
    fini_static_exctypes(state, interp);
165
0
    return -1;
166
16
}
167
168
static void
169
fini_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
170
0
{
171
0
    assert(state == &_PyXI_GET_STATE(interp)->exceptions);
172
0
    if (state->PyExc_InterpreterNotFoundError != NULL) {
173
0
        state->PyExc_InterpreterNotFoundError = NULL;
174
0
        _PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterNotFoundError);
175
0
    }
176
0
    if (state->PyExc_InterpreterError != NULL) {
177
0
        state->PyExc_InterpreterError = NULL;
178
0
        _PyStaticType_FiniBuiltin(interp, &_PyExc_InterpreterError);
179
0
    }
180
0
}
181
182
static int
183
init_heap_exctypes(exceptions_t *state)
184
16
{
185
16
    if (_init_notshareableerror(state) < 0) {
186
0
        goto error;
187
0
    }
188
16
    return 0;
189
190
0
error:
191
0
    fini_heap_exctypes(state);
192
0
    return -1;
193
16
}
194
195
static void
196
fini_heap_exctypes(exceptions_t *state)
197
0
{
198
0
    _fini_notshareableerror(state);
199
0
}