robust clean-up with SIGTERM (was Re: Again, how to write a cleanup function for a module in C )

Changjune Kim juneaftn at REMOVETHIShanmail.net
Sat Aug 16 00:21:29 CEST 2003


Though I'm not Alex Martelli, hope this helps: (look at the end of this
post)

"Jane Austine" <janeaustine50 at hotmail.com> wrote in message
news:ba1e306f.0308131051.3b6bcbd3 at posting.google.com...
> I'm writing a cgi script. The user can push the stop button at any
> moment while the page is loading, and the apache will raise SIGTERM
> and then SIGKILL in 3 secs. And the garbage is not collected
> automatically when the signals are raised. It's an abnormal
> termination.
>
> I need to clean up a few things(like closing the db connection) before
> the interpreter terminates.
>
> How do I?
>
> And according to Alex's suggestions... (see my questions below)
>
> "Alex Martelli" <aleax at aleax.it> wrote:
>
> [snip]
> >
> > 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.
> >
> >
> [snip]
> >
> > So, handle the signal, and make the program die "cleanly" with the
> > exception of your choice -- THEN, cleanup code DOES run.
> >
> [snip]
>
> This "signal to exception translation" looks nice. But Alex said
> "won't work all of the time, but, pretty often". I am afraid to use
> this method if its safety is not guaranteed. I wonder in what cases it
> does not work, and how I can make it work always.

When signals are generated successively in a very short time, python
interpreter might screw up some of them. Basically, the interpreter checks
every checkinterval(default 100) if it has pending signal handler calls,
and process them. When a signal is generated, it registers the signal and
put its handler on the pending calls. As you can see there are potential
race conditions.

Check signalmodule.c and ceval.c.

I don't have a good idea on making signal handling always safe &
guaranteed. Maybe someone else can help?





More information about the Python-list mailing list