New issue 3096: PyErr_SetExcInfo(NULL, NULL, NULL) does not fully clear current 
thread exception context
https://bitbucket.org/pypy/pypy/issues/3096/pyerr_setexcinfo-null-null-null-does-not

Kirill Smelkov:

Hello up there. Please consider the following example:

\(mysys.pyx\)

```python
# cython: language_level=3
cdef extern from "Python.h":
    struct PyObject
    void PyErr_SetExcInfo(PyObject*, PyObject*, PyObject*)

# exc_clear is like sys.exc_clear() on py2 - it clears current thread's caught 
exception state.
def exc_clear():
    PyErr_SetExcInfo(NULL, NULL, NULL)
```

\(mysys\_test.py\)

‌

```
import mysys

def recover():
    mysys.exc_clear()

def main2():
    try:
        raise RuntimeError('aaa')
    finally:
        recover()
        raise RuntimeError('bbb')


def main():
    main2()
    """
    try:
        main2()
    except Exception as e:
        print(repr(e))
        print('__cause__:',     e.__cause__)
        print('__context__:',   e.__context__)
        print(dir(e))
    """

if __name__ == '__main__':
    main()
```

When run with CPython-3.7 it prints only ‘bbb’:

‌

```
$ python3.7 mysys_test.py 
Traceback (most recent call last):
  File "mysys_test.py", line 27, in <module>
    main()
  File "mysys_test.py", line 15, in main
    main2()
  File "mysys_test.py", line 11, in main2
    raise RuntimeError('bbb')
RuntimeError: bbb
```

but when run with PyPy3.6-7.2 it prints both ‘bbb’ _**and**_ ‘aaa’:

‌

```
$ pypy3 mysys_test.py 
Traceback (most recent call last):
  File "mysys_test.py", line 8, in main2
    raise RuntimeError('aaa')
RuntimeError: aaa

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "mysys_test.py", line 27, in <module>
    main()
  File "mysys_test.py", line 15, in main
    main2()
  File "mysys_test.py", line 11, in main2
    raise RuntimeError('bbb')
RuntimeError: bbb
```

If I uncomment printing code in main, it shows that under cpython 
`e.__context__ is None` while under pypy `e.__context__` points to 
`RuntimeError('aaa')`.

If I put `mysys.exc_clear()` directly into `finally` block without doing it 
through `recover()` call, the bug goes away.

‌

```
$ pypy3 --version
Python 3.6.9 (5da45ced70e5, Oct 09 2019, 19:12:54)
[PyPy 7.2.0 with GCC 6.2.0 20160901]
```

The bug also happens with pypy-7.0 and 7.1. 

The bug was caught while testing pygolang on pypy3 and is minimal example of 
what happens there in `defer` and `recover` functionality.

Thanks beforehand,  
Kirill

/cc @{557058:7cb88866-fb18-487e-a2dc-b19de69f5f0b} 

‌


_______________________________________________
pypy-issue mailing list
pypy-issue@python.org
https://mail.python.org/mailman/listinfo/pypy-issue

Reply via email to