Skip to content

Commit 2135a3f

Browse files
Optionally set __cause__.
1 parent 0997471 commit 2135a3f

File tree

3 files changed

+50
-20
lines changed

3 files changed

+50
-20
lines changed

Python/crossinterp.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -199,19 +199,20 @@ _check_xidata(PyThreadState *tstate, _PyXIData_t *data)
199199
}
200200

201201
static inline void
202-
_set_xid_lookup_failure(PyThreadState *tstate, PyObject *obj, const char *msg)
202+
_set_xid_lookup_failure(PyThreadState *tstate, PyObject *obj, const char *msg,
203+
PyObject *cause)
203204
{
204205
if (msg != NULL) {
205206
assert(obj == NULL);
206-
set_notshareableerror(tstate, msg);
207+
set_notshareableerror(tstate, cause, msg);
207208
}
208209
else if (obj == NULL) {
209-
set_notshareableerror(
210-
tstate, "object does not support cross-interpreter data");
210+
msg = "object does not support cross-interpreter data";
211+
set_notshareableerror(tstate, cause, msg);
211212
}
212213
else {
213-
_PyXIData_FormatNotShareableError(
214-
tstate, "%S does not support cross-interpreter data", obj);
214+
format_notshareableerror(
215+
tstate, cause, "%S does not support cross-interpreter data", obj);
215216
}
216217
}
217218

@@ -225,7 +226,7 @@ _PyObject_CheckXIData(PyThreadState *tstate, PyObject *obj)
225226
xidatafunc getdata = lookup_getdata(&ctx, obj);
226227
if (getdata == NULL) {
227228
if (!PyErr_Occurred()) {
228-
_set_xid_lookup_failure(tstate, obj, NULL);
229+
_set_xid_lookup_failure(tstate, obj, NULL, NULL);
229230
}
230231
return -1;
231232
}
@@ -252,7 +253,7 @@ _PyObject_GetXIData(PyThreadState *tstate,
252253
if (getdata == NULL) {
253254
Py_DECREF(obj);
254255
if (!PyErr_Occurred()) {
255-
_set_xid_lookup_failure(tstate, obj, NULL);
256+
_set_xid_lookup_failure(tstate, obj, NULL, NULL);
256257
}
257258
return -1;
258259
}
@@ -1003,7 +1004,7 @@ _PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
10031004
"failed to apply namespace to __main__");
10041005
break;
10051006
case _PyXI_ERR_NOT_SHAREABLE:
1006-
_set_xid_lookup_failure(tstate, NULL, NULL);
1007+
_set_xid_lookup_failure(tstate, NULL, NULL, NULL);
10071008
break;
10081009
default:
10091010
#ifdef Py_DEBUG
@@ -1066,7 +1067,7 @@ _PyXI_ApplyError(_PyXI_error *error)
10661067
}
10671068
else if (error->code == _PyXI_ERR_NOT_SHAREABLE) {
10681069
// Propagate the exception directly.
1069-
_set_xid_lookup_failure(tstate, NULL, error->uncaught.msg);
1070+
_set_xid_lookup_failure(tstate, NULL, error->uncaught.msg, NULL);
10701071
}
10711072
else {
10721073
// Raise an exception corresponding to the code.

Python/crossinterp_data_lookup.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,16 +72,18 @@ _PyXIData_GetNotShareableErrorType(PyThreadState *tstate)
7272
void
7373
_PyXIData_SetNotShareableError(PyThreadState *tstate, const char *msg)
7474
{
75-
set_notshareableerror(tstate, msg);
75+
PyObject *cause = NULL;
76+
set_notshareableerror(tstate, cause, msg);
7677
}
7778

7879
void
7980
_PyXIData_FormatNotShareableError(PyThreadState *tstate,
8081
const char *format, ...)
8182
{
83+
PyObject *cause = NULL;
8284
va_list vargs;
8385
va_start(vargs, format);
84-
format_notshareableerror_v(tstate, format, vargs);
86+
format_notshareableerror_v(tstate, cause, format, vargs);
8587
va_end(vargs);
8688
}
8789

Python/crossinterp_exceptions.h

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,24 @@
11

2+
static void
3+
_ensure_current_cause(PyThreadState *tstate, PyObject *cause)
4+
{
5+
if (cause == NULL) {
6+
return;
7+
}
8+
PyObject *exc = _PyErr_GetRaisedException(tstate);
9+
assert(exc != NULL);
10+
PyObject *ctx = PyException_GetContext(exc);
11+
if (ctx == NULL) {
12+
PyException_SetContext(exc, cause);
13+
}
14+
else {
15+
Py_DECREF(ctx);
16+
}
17+
assert(PyException_GetCause(exc) == NULL);
18+
PyException_SetCause(exc, cause);
19+
}
20+
21+
222
/* InterpreterError extends Exception */
323

424
static PyTypeObject _PyExc_InterpreterError = {
@@ -60,7 +80,7 @@ get_notshareableerror_type(PyThreadState *tstate)
6080
}
6181

6282
static void
63-
set_notshareableerror(PyThreadState *tstate, const char *msg)
83+
set_notshareableerror(PyThreadState *tstate, PyObject *cause, const char *msg)
6484
{
6585
PyObject *exctype = get_notshareableerror_type(tstate);
6686
if (exctype == NULL) {
@@ -70,13 +90,12 @@ set_notshareableerror(PyThreadState *tstate, const char *msg)
7090
PyObject *ctx = _PyErr_GetRaisedException(tstate);
7191
_PyErr_SetString(tstate, exctype, msg);
7292
_PyErr_ChainExceptions1Tstate(tstate, ctx);
73-
// XXX Ideally we would also append the currently handling exception
74-
// (_PyErr_GetTopmostException()->exc_value) to the end of ctx's
75-
// context chain. (See _PyErr_SetObject().)
93+
_ensure_current_cause(tstate, cause);
7694
}
7795

7896
static void
79-
format_notshareableerror_v(PyThreadState *tstate, const char *format, va_list vargs)
97+
format_notshareableerror_v(PyThreadState *tstate, PyObject *cause,
98+
const char *format, va_list vargs)
8099
{
81100
PyObject *exctype = get_notshareableerror_type(tstate);
82101
if (exctype == NULL) {
@@ -86,9 +105,17 @@ format_notshareableerror_v(PyThreadState *tstate, const char *format, va_list va
86105
PyObject *ctx = _PyErr_GetRaisedException(tstate);
87106
_PyErr_FormatV(tstate, exctype, format, vargs);
88107
_PyErr_ChainExceptions1Tstate(tstate, ctx);
89-
// XXX Ideally we would also append the currently handling exception
90-
// (_PyErr_GetTopmostException()->exc_value) to the end of ctx's
91-
// context chain. (See _PyErr_SetObject().)
108+
_ensure_current_cause(tstate, cause);
109+
}
110+
111+
static void
112+
format_notshareableerror(PyThreadState *tstate, PyObject *cause,
113+
const char *format, ...)
114+
{
115+
va_list vargs;
116+
va_start(vargs, format);
117+
format_notshareableerror_v(tstate, cause, format, vargs);
118+
va_end(vargs);
92119
}
93120

94121

0 commit comments

Comments
 (0)