octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

signal handling


From: John W. Eaton
Subject: signal handling
Date: Tue, 5 Nov 2002 11:59:41 -0600

I'm thinking about how to improve Octave's signal handling and error
recovery.  Currently, when Octave receives an interrupt signal, it
simply tries to use longjump to get back to the beginning of the main
interpreter loop.  This approach has at least two major problems.
First, there is no guarantee that a longjump out of a signal handler
will even work.  Second, it skips over the destructors for all the
objects that have been created up to the point of the signal, which
leads to big memory leaks.

The program below provides an outline of how signal handling in Octave
currently works and also how I propose to improve it.  If you compile
without -DUSE_EXCEPTIONS, you will get the current behavior.  Run it
and type Control-C a few times just after the "sleeping" message
appears (so you are sure to have some memory allocated by an
intermediate object) and watch the process grow (with top, ps,
whatever).  It should grow in increments of about 8MB and you should
see more messages from the big_memory_hog constructor than from the
destructor.

My proposal is to modify the signal handler so that it simply sets a
global variable and returns.  Then when Octave hits a QUIT macro, it
will throw a C++ exception which will be caught at the top level.  If
we then make sure that all resources are managed properly in object
constructors/destructors, the exception handling code should take care
of deleting any temporary objects.  I think that in most instances,
this is already true, so most of that work is done.  What remains is
to add calls to QUIT in a number of places in the Octave sources.  To
see how this method works, compile the example below with
-DUSE_EXCEPTIONS and try the same experiment as above.  This time, you
should see the same number of messages from the big_memory_hog
constructor and destructor so the process should not grow (the total
size should never be too much more than 8MB).

This method will take care of exceptions that happen in the C++ code
that Octave uses.  For the Fortran bits and other library code that we
call, I think we will need a slightly different approach.  But we only
have to worry about code that may run for a significant amount of time
(otherwise, we just wait for it to finish, and the exception handling
stuff will take care of getting us back to the top level without too
much delay).

My proposal for Fortran or other long-running foreign code is to set
up a separate signal handling/longjump scheme around them.  The idea
is that when an interrupt signal is received, we will jump out of the
signal handler, but only back to the point where the foreign code was
called.  Then we throw an exception and make our way back to the top
level, using the exception handler code to clean up as we go.  This
does not solve the problem of resource management for the foriegn code
or on systems where jumping out of a signal handler does not work (I
don't know what to do about that, other than ignore interrupts on
those systems).  It is OK for the Fortran code that Octave uses
because that stuff doesn't do any memory allocations and typically
does not open external files.  But for other foriegn code, we may leak
memory or other resources.  The only solution I can see for that is to
make sure that the foreign code manages its resources properly in the
presence of interrupt signals.

Comments?

Thanks,

jwe


Attachment: except.cc
Description: Binary data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]