Skip to content

Commit 6c77666

Browse files
author
James William Pye
committed
Set the exception's context.
Apparently, the C-APIs used here don't cause the context to be attached to the raise in the exception handler called by process_tuple.
1 parent ce016e3 commit 6c77666

1 file changed

Lines changed: 38 additions & 3 deletions

File tree

postgresql/protocol/optimized.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,20 @@ process_tuple(PyObject *self, PyObject *args)
229229
*/
230230
Py_DECREF(rob);
231231
rob = NULL;
232+
233+
/*
234+
* Don't trap BaseException's.
235+
*/
232236
if (PyErr_ExceptionMatches(PyExc_Exception))
233237
{
234238
PyObject *failargs, *failedat;
235-
/*
236-
* It's *not* a BaseException.
237-
*/
239+
PyObject *exc, *val, *tb;
240+
PyObject *oldexc, *oldval, *oldtb;
241+
242+
/* Store exception to set context after handler. */
243+
PyErr_Fetch(&oldexc, &oldval, &oldtb);
244+
PyErr_NormalizeException(&oldexc, &oldval, &oldtb);
245+
238246
failedat = PyLong_FromSsize_t(i);
239247
if (failedat != NULL)
240248
{
@@ -261,6 +269,33 @@ process_tuple(PyObject *self, PyObject *args)
261269
Py_DECREF(failedat);
262270
}
263271
}
272+
273+
PyErr_Fetch(&exc, &val, &tb);
274+
PyErr_NormalizeException(&exc, &val, &tb);
275+
276+
/*
277+
* Reference BaseException here as the condition is merely
278+
* *validating* that SetContext can be used.
279+
*/
280+
if (val != NULL && PyObject_IsInstance(val, PyExc_BaseException))
281+
{
282+
/* Steals oldval reference */
283+
PyException_SetContext(val, oldval);
284+
Py_XDECREF(oldexc);
285+
Py_XDECREF(oldtb);
286+
PyErr_Restore(exc, val, tb);
287+
}
288+
else
289+
{
290+
/*
291+
* Fetch & NormalizeException failed somehow.
292+
* Use the old exception...
293+
*/
294+
PyErr_Restore(oldexc, oldval, oldtb);
295+
Py_XDECREF(exc);
296+
Py_XDECREF(val);
297+
Py_XDECREF(tb);
298+
}
264299
}
265300

266301
/*

0 commit comments

Comments
 (0)