no cleanup on TERM signal

Laszlo Nagy gandalf at shopzeus.com
Fri May 2 05:43:10 EDT 2008


Yves Dorfsman wrote:
> I did a few tests with this script:
>
> class byebye:
>
>   def __del__(self):
>     print 'Bye, bye...'
>
>
> x = byebye()
>
>
> x.del() gets executed if:
> -I del x, then run gc.collect()
> -simply exit the script
> -get the script to abort on an exception
>
> But if I kill it with the default signal TERM, the script dies, but I 
> don't get the message, so I am assuming that python isn't taking the 
> time to cleanup, even though that is (was) what TERM was intended for.
TERM signal is unix specific. There is no special syntax/programming 
structure for signals inside the Python language, since it would be 
platform dependent. For simple client programs, usually it is not needed 
to setup signal handlers because they can easily be controlled in other 
ways.

For sensitive resources, instead of writing __del__ methods, you should 
create a "close()" method. Python does this with file objects, DB API 
2.0 with database connection objects etc. Then you can do

res = create_resource()
try:
    use_resource()
finally:
    res.close() # Must free resource, but the object can still be alive...

It is more common to use signals when you have more threads or child 
processes. You can use something like:

import threading
import signal

stop_requested = threading.Event()
exited_on_sigterm = False

def free_all_resources():
    pass # Free your resources here!

def sigterm_handler(signum, frame):
    """Stop the server gracefully when on SIGTERM."""
    global stop_requested
    global exited_on_sigterm
    exited_on_sigterm = True
    stop_requested.set()
    free_all_resources()

def main():
    global stop_requested
    global exited_on_sigterm

    logger = servicelog.getLogger('main',filename=LOGFILENAME)

    logger.info('Setting up the SIGTERM signal handler.')
    signal.signal(signal.SIGTERM, sigterm_handler) # Setup signal handler

    logger.info('Starting watchdog thread')
    watchdog = WatchDog()
    watchdog.start()

    worker1 = create_worker(stop_requested)
    worker2 = create_worker(stop_requested)
    # etc. Prepare things here...
   
    try:
        try:
            server = create_my_server()
            server.serve_until_not_stopped()              
        except Exception, e:
            logger.error(dumpexc(e))
            raise e
    finally:
        stop_requested.set()  # Ask other threads to stop cooperatively
      
        # Join all threads here
        watchdog.join()
        worker1.join()
        worder2.join()
        # etc. wait for all threads to exit cooperatively.
        if exited_on_sigterm:
            logger.warning('Exited on SIGTERM!')

Best,

   Laszlo




More information about the Python-list mailing list