Cleanups and Exception handlers

Phil Muldoon pmuldoon@redhat.com
Wed May 1 10:28:00 GMT 2013


I'd like to quantify and discuss strategies of cleanups and GDB exception
handlers.  It seems I am always making mistakes in this area, and the
comments in the TRY_CATCH macro (well to me) are not adequate about the
mechanics of cleanups in an exception handler.

So I would like to discuss patterns of usage with a view to updating
the comments to be more explanatory.

Take this example, something that caught me out recently:

  struct cleanups cleanups;

  cleanups = make_cleanup (xfree, foo);

  TRY_CATCH (except, RETURN_MASK_ALL)
    {
      make_cleanup_ui_out_tuple_begin_end (out, NULL);	
      ...
      // Do some other stuff
    }
  if (except.reason < 0)
    {
      // Some exception handling code
    }

  do_cleanups (cleanups);

It seems if you create a cleanup in an exception handler, even if the
old cleanup chain is saved before the exception handler starts, you
have to call do_cleanups() in the exception handler or the cleanup is
lost. It seems that the TRY_CATCH code is manipulating the cleanup
chain,  but I can't find any comments on why it does this, or how that
affects your own cleanup chain.  What happens if you discard cleanups
in an exception handler to a point where the cleanup was registered
before the exception handler started?

In the above example, assuming everything went OK in above, and no
calls produced an error() or some other call, when I call
do_cleanups() in that code, my "tuple" cleanup seems to have been
discarded.  (I know this as in my code, I rapidly encounter
ui_out->level > MAX_UI_OUT_LEVELS as the tuples were never closed in
the cleanups.

Question 1)

What is the rule regarding cleanup chains that were created outside of
an exception handler, but where additional cleanups were registered
and not processed (cleanedup) inside the exception handler.

Question 2)

If in the above example, something goes wrong, does one have to call
do_cleanups() in the exception handling block (IE if (except.reason <
0))

Example 2:


  TRY_CATCH (except, RETURN_MASK_ALL)
  {
    struct cleanups cleanups =
      make_cleanup_ui_out_tuple_begin_end (out, NULL);	
      ...
      // Do some other stuff
    do_cleanups (cleanups);	
    }
  if (except.reason < 0)
    {
      // Some exception handling code
    }

In this example we create a pointer to the cleanup chain, and perform
a tuple cleanup.  If I call do_cleanups() in this example (assuming
nothing went wrong in the TRY_CATCH block), the tuple is cleaned up
properly.  But what happens if something happens and the exception
handling "if" is called.

Question 3)

For cleanups created and registered exclusively in the TRY_CATCH
block, on some exception being raised are they cleaned up
automatically?  (As there is no scope for the exception handling
failure code to do cleanups).

This all came about as MI tuples tend to be "long lived" cleanups and
in Python we have to handle every potential GDB exception call in an
exception handler to prevent propagation upwards.  I found this leads
to giant TRY_CATCH calls that encompass tuple creation, tuple
population, and tuple closure. But I am not sure.

Cheers,

Phil



More information about the Gdb mailing list