Again, how to write a cleanup function for a module in C

Alex Martelli aleax at aleax.it
Sat Mar 29 12:05:36 EST 2003


Lexy Zhitenev wrote:

> "Alex Martelli" <aleax at aleax.it> wrote:
> news:g8_ga.33370$i26.870013 at news2.tin.it...
> 
>> See standard Python library module atexit.
>>
>> Alex
> 
> Yes, Alex, but this method won't work if my program is killed by an
> exception or by signal. The method that I use cleans things up on
> exception.

Are you implying that atexit doesn't?  Run the following script:

import atexit
def f(*args):
    print 'f',args
atexit.register(f,'goo','bar','baz')
1/0

The output I see for it is as follows:

[alex at lancelot src]$ python2.2 a.py
Traceback (most recent call last):
  File "a.py", line 5, in ?
    1/0
ZeroDivisionError: integer division or modulo by zero
f ('goo', 'bar', 'baz')
[alex at lancelot src]$


Signals are nastier -- by default they terminate the process
WITHOUT cleanup.  For example, if instead of the 1/0 you have
at the end of the script:

import os, signal
os.kill(os.getpid(), signal.SIGIO)

then f won't get run.  Easy solution (won't work all of the
time, but, pretty often): handle the signal to turn it into
an exception!  e.g. change the above two lines to:

import os, signal
def sig2exc(sig, frm): raise SystemError(sig)
signal.signal(signal.SIGIO, sig2exc)
os.kill(os.getpid(), signal.SIGIO)

and f will again execute.


> If I register a cleanup function in atexit while debugging, when most of
> time my program terminates with an exception, my memory will leak
> tremendously.

I'm not sure how memory can leak when your process dies, but maybe
that was explained in your earlier postings -- not very relevant,
anyway, because, whether memory-related or not, it's certain that
your cleanup code won't execute if your process dies due to an
unhandled signal (or to os._exit -- that one exists SPECIFICALLY to
have the process die _at once_, BYPASSING all cleanup).

So, handle the signal, and make the program die "cleanly" with the
exception of your choice -- THEN, cleanup code DOES run.

If some signals indicate you've messed things up so badly that it's
NOT safe to run Python itself or most cleanup code, then, for those
signals, you'll obviously have to set C handlers that just perform
the minimal cleanup that you know can and must still be performed
despite the mess.  But there, of course, Python can't help, because
we're hypothesizing that things are in such a mess that Python itself
can't safely run any more.


> Possibly, there should be a PEP for that...

Feel free to draft the PEP, but it would be nice if you had some
convincing arguments in it proving that there IS something that
can usefully be done and which you cannot handle satisfactorily
with the existing tools (such as atexit, and signal handlers).


Alex





More information about the Python-list mailing list