catacomb-python.h, *.c: Fix how Python `pgen' handlers handle exceptions.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 14 Nov 2019 19:08:53 +0000 (19:08 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Fri, 22 Nov 2019 22:18:11 +0000 (22:18 +0000)
commit930d78e3e2045f6f810c73edd81f44321b039ea5
treebf4b19e9b683d3cc382e61ed0dcf85f346b7aa1f
parenta42955d587b9ed267aa9a22d5b68f89b4d88beb5
catacomb-python.h, *.c: Fix how Python `pgen' handlers handle exceptions.

Oh, this was a mess.  The old code would convert an exception from a
Python handler into `PGEN_ABORT', and hope that the exception state was
still available when the overall operation ended.

This doesn't work.  In particular, steppers and testers are finalized by
calling them with `PGEN_DONE', and the interpreter doesn't like
re-entering Python with an exception set.  (In debug builds, this is an
assertion failure.)

Overhaul all of this nonsense.

  * Add a collection of utilities for saving and restoring the exception
    state.

  * Add a hook, in the `catacomb' module, for reporting `lost'
    exceptions, for the case where further exceptions are raised while
    responding to a first exception.

  * Use a larger `pypgev' structure to track the state of a Python event
    handler through the framework.  This structure holds a reference to
    the Python object itself, and a slot for recording an exception.

  * When a Python handler fails, stash the exception state in the slot
    provided by the `pypgev' structure if there isn't one already, and
    clear the pending exception.  If there is already an exception in
    the slot, then report the new exception through the hook described
    above.

  * Once a `pgen' operation completes, if it raised any exceptions at
    all, then the first of these is left in the exception slot.  If it
    fails otherwise, then we supply a generic exception.
catacomb-python.h
catacomb/__init__.py
group.c
pgen.c
pubkey.c
rand.c
util.c