Author: Ronan Lamy <[email protected]>
Branch:
Changeset: r91836:5adabc9b9848
Date: 2017-07-08 01:17 +0100
http://bitbucket.org/pypy/pypy/changeset/5adabc9b9848/
Log: Fix calling PyErr_Fetch() + PyErr_NormalizeException() with no
exception set
diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -95,8 +95,18 @@
not an instance of the same class. This function can be used to
instantiate
the class in that case. If the values are already normalized, nothing
happens.
The delayed normalization is implemented to improve performance."""
- operr = OperationError(from_ref(space, exc_p[0]),
- from_ref(space, val_p[0]))
+ if exc_p[0]:
+ w_etype = from_ref(space, exc_p[0])
+ else:
+ # There is no exception, so nothing to do
+ return
+ if val_p[0]:
+ w_evalue = from_ref(space, val_p[0])
+ else:
+ # On CPython, PyErr_SetNone actually sets val to NULL.
+ # Sensible code should probably never trigger this path on PyPy, but...
+ w_evalue = space.w_None
+ operr = OperationError(w_etype, w_evalue)
operr.normalize_exception(space)
Py_DecRef(space, exc_p[0])
Py_DecRef(space, val_p[0])
@@ -388,9 +398,9 @@
freshly raised. This function steals the references of the arguments.
To clear the exception state, pass *NULL* for all three arguments.
For general rules about the three arguments, see :c:func:`PyErr_Restore`.
-
+
.. note::
-
+
This function is not normally used by code that wants to handle
exceptions. Rather, it can be used when code needs to save and
restore the exception state temporarily. Use
diff --git a/pypy/module/cpyext/test/test_pyerrors.py
b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -177,6 +177,23 @@
])
assert module.check_error()
+ def test_normalize_no_exception(self):
+ module = self.import_extension('foo', [
+ ("check_error", "METH_NOARGS",
+ '''
+ PyObject *type, *val, *tb;
+ PyErr_Fetch(&type, &val, &tb);
+ if (type != NULL)
+ Py_RETURN_FALSE;
+ if (val != NULL)
+ Py_RETURN_FALSE;
+ PyErr_NormalizeException(&type, &val, &tb);
+ Py_RETURN_TRUE;
+ '''
+ ),
+ ])
+ assert module.check_error()
+
def test_SetFromErrno(self):
import sys
if sys.platform != 'win32':
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit