/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 | } |