]> granicus.if.org Git - python/commitdiff
Issue #18609, #18408: _ctypes_add_traceback() now clears the current exception
authorVictor Stinner <victor.stinner@gmail.com>
Thu, 1 Aug 2013 22:47:47 +0000 (00:47 +0200)
committerVictor Stinner <victor.stinner@gmail.com>
Thu, 1 Aug 2013 22:47:47 +0000 (00:47 +0200)
while adding the traceback, because it may call indirectly a Python function
and Python functions must not be called with an exception set.

In the case of the issue #18609, _ctypes_add_traceback() called the iso8859-1
decoder which is implemented in Python. Python has a ISO-8859-1 codec
implemented in C. It is not used because PyUnicode_Decode() only uses the C
codec for other names (aliases) of this codec ("latin-1", "latin1" and
"iso-8859-1").

Modules/_ctypes/callbacks.c

index 34c46ad7a7eeaacbb95435121c2c14adaa91eb07..86232395926bb17b585e8e324571432992307b1c 100644 (file)
@@ -98,20 +98,37 @@ void _ctypes_add_traceback(char *funcname, char *filename, int lineno)
     PyObject *py_globals = 0;
     PyCodeObject *py_code = 0;
     PyFrameObject *py_frame = 0;
+    PyObject *exception, *value, *tb;
+
+    /* (Save and) Clear the current exception. Python functions must not be
+       called with an exception set. Calling Python functions happens when
+       the codec of the filesystem encoding is implemented in pure Python. */
+    PyErr_Fetch(&exception, &value, &tb);
 
     py_globals = PyDict_New();
-    if (!py_globals) goto bad;
+    if (!py_globals)
+        goto bad;
     py_code = PyCode_NewEmpty(filename, funcname, lineno);
-    if (!py_code) goto bad;
+    if (!py_code)
+        goto bad;
     py_frame = PyFrame_New(
         PyThreadState_Get(), /*PyThreadState *tstate,*/
         py_code,             /*PyCodeObject *code,*/
         py_globals,          /*PyObject *globals,*/
         0                    /*PyObject *locals*/
         );
-    if (!py_frame) goto bad;
+    if (!py_frame)
+        goto bad;
     py_frame->f_lineno = lineno;
+
+    PyErr_Restore(exception, value, tb);
     PyTraceBack_Here(py_frame);
+
+    Py_DECREF(py_globals);
+    Py_DECREF(py_code);
+    Py_DECREF(py_frame);
+    return;
+
   bad:
     Py_XDECREF(py_globals);
     Py_XDECREF(py_code);