Exception stomping

Eric Huss <[email protected]> Tue, 25 Nov 2008 16:27:25 -0800 (PST)
Newsgroups gmane.comp.python.pyrex
Message-ID <[email protected]>
I've run into a problem with how Pyrex handles the "current" exception
(not sure if this has been discussed before).  I know that the "reraise"
issue has been fixed, but this is a slightly different issue where Pyrex
does not make a backup of the "current" exception.

If you call a Pyrex function that internally raises and catches an
exception, but does not re-raise it, it leaves that exception set within
the tstate object.  This causes the exception to bleed out in unexpected
ways.

Attached is an example that illustrates the problem.

In the Python interpreter, when you leave a frame, it typically restores
tstate->exc_* (via the reset_exc_info function) to whatever it used to be
(the backup kept inside the frame object).  Pyrex does not make a backup,
and inside __Pyx_GetException it stomps on tstate->exc_*.

Perhaps a solution would be to emulate what set_exc_info/reset_exc_info do
inside the interpreter using local variables stored on the C stack,
similar to how the "reraise" fix was implemented.

My only thought on a workaround at the moment is to somehow manually
backup tstate->exc_* in any Pyrex function that has an exception handler
that does not reraise.  However, that is pretty messy and prone to subtle
bugs and refcount issues, so I'm a little reluctant to head that way.

-Eric

_______________________________________________
Pyrex mailing list
[email protected]
http://lists.copyleft.no/mailman/listinfo/pyrex
test_exc_main.py (text/plain, 309 B)
import test_exc

def foo():
    try:
        raise ValueError(3)
    except ValueError:
        raise


def test():
    try:
        foo()
    except:
        test_exc.bar()
        # Re-raise foo exception which should be ValueError(3)
        raise

if __name__ == '__main__':
    test()
test_exc.pyx (text/plain, 89 B)
def bar():
    try:
        raise ValueError(4)
    except ValueError:
        pass