@@ -21,7 +21,8 @@ PyObject *PLy_exc_fatal = NULL;
2121PyObject * PLy_exc_spi_error = NULL ;
2222
2323
24- static void PLy_traceback (char * * xmsg ,char * * tbmsg ,int * tb_depth );
24+ static void PLy_traceback (PyObject * e ,PyObject * v ,PyObject * tb ,
25+ char * * xmsg ,char * * tbmsg ,int * tb_depth );
2526static void PLy_get_spi_error_data (PyObject * exc ,int * sqlerrcode ,char * * detail ,
2627char * * hint ,char * * query ,int * position );
2728static char * get_source_line (const char * src ,int lineno );
@@ -53,16 +54,20 @@ PLy_elog(int elevel, const char *fmt,...)
5354int position = 0 ;
5455
5556PyErr_Fetch (& exc ,& val ,& tb );
57+
5658if (exc != NULL )
5759{
60+ PyErr_NormalizeException (& exc ,& val ,& tb );
61+
5862if (PyErr_GivenExceptionMatches (val ,PLy_exc_spi_error ))
5963PLy_get_spi_error_data (val ,& sqlerrcode ,& detail ,& hint ,& query ,& position );
6064else if (PyErr_GivenExceptionMatches (val ,PLy_exc_fatal ))
6165elevel = FATAL ;
6266}
63- PyErr_Restore (exc ,val ,tb );
6467
65- PLy_traceback (& xmsg ,& tbmsg ,& tb_depth );
68+ /* this releases our refcount on tb! */
69+ PLy_traceback (exc ,val ,tb ,
70+ & xmsg ,& tbmsg ,& tb_depth );
6671
6772if (fmt )
6873{
@@ -113,6 +118,9 @@ PLy_elog(int elevel, const char *fmt,...)
113118pfree (xmsg );
114119if (tbmsg )
115120pfree (tbmsg );
121+ Py_XDECREF (exc );
122+ Py_XDECREF (val );
123+
116124PG_RE_THROW ();
117125}
118126PG_END_TRY ();
@@ -123,21 +131,24 @@ PLy_elog(int elevel, const char *fmt,...)
123131pfree (xmsg );
124132if (tbmsg )
125133pfree (tbmsg );
134+ Py_XDECREF (exc );
135+ Py_XDECREF (val );
126136}
127137
128138/*
129- * Extract a Python traceback from thecurrent exception.
139+ * Extract a Python traceback from thegiven exception data .
130140 *
131141 * The exception error message is returned in xmsg, the traceback in
132142 * tbmsg (both as palloc'd strings) and the traceback depth in
133143 * tb_depth.
144+ *
145+ * We release refcounts on all the Python objects in the traceback stack,
146+ * but not on e or v.
134147 */
135148static void
136- PLy_traceback (char * * xmsg ,char * * tbmsg ,int * tb_depth )
149+ PLy_traceback (PyObject * e ,PyObject * v ,PyObject * tb ,
150+ char * * xmsg ,char * * tbmsg ,int * tb_depth )
137151{
138- PyObject * e ,
139- * v ,
140- * tb ;
141152PyObject * e_type_o ;
142153PyObject * e_module_o ;
143154char * e_type_s = NULL ;
@@ -148,12 +159,7 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
148159StringInfoData tbstr ;
149160
150161/*
151- * get the current exception
152- */
153- PyErr_Fetch (& e ,& v ,& tb );
154-
155- /*
156- * oops, no exception, return
162+ * if no exception, return nulls
157163 */
158164if (e == NULL )
159165{
@@ -164,8 +170,6 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
164170return ;
165171}
166172
167- PyErr_NormalizeException (& e ,& v ,& tb );
168-
169173/*
170174 * Format the exception and its value and put it in xmsg.
171175 */
@@ -332,8 +336,6 @@ PLy_traceback(char **xmsg, char **tbmsg, int *tb_depth)
332336Py_XDECREF (e_type_o );
333337Py_XDECREF (e_module_o );
334338Py_XDECREF (vob );
335- Py_XDECREF (v );
336- Py_DECREF (e );
337339}
338340
339341/*
@@ -367,7 +369,7 @@ PLy_get_spi_sqlerrcode(PyObject *exc, int *sqlerrcode)
367369static void
368370PLy_get_spi_error_data (PyObject * exc ,int * sqlerrcode ,char * * detail ,char * * hint ,char * * query ,int * position )
369371{
370- PyObject * spidata = NULL ;
372+ PyObject * spidata ;
371373
372374spidata = PyObject_GetAttrString (exc ,"spidata" );
373375
@@ -384,8 +386,6 @@ PLy_get_spi_error_data(PyObject *exc, int *sqlerrcode, char **detail, char **hin
384386PLy_get_spi_sqlerrcode (exc ,sqlerrcode );
385387}
386388
387- PyErr_Clear ();
388- /* no elog here, we simply won't report the errhint, errposition etc */
389389Py_XDECREF (spidata );
390390}
391391