The invocation of signal handler and atexit handler in Python
Asked Answered
J

1

6

I have a piece of Python code as below:

import sys
import signal
import atexit

def release():
    print "Release resources..."

def sigHandler(signo, frame):
    release()
    sys.exit(0)

if __name__ == "__main__":
    signal.signal(signal.SIGTERM, sigHandler)
    atexit.register(release)

    while True:
        pass

The real code is far more complex than this snippets, but the structures are the same: i.e. main function maintains an infinite loop.

I need a signal callback to release the resources occupied, like DB handle. Then I add a SIGTERM handler, in case the server is killed, which simply invoke the release function and then exit the process. The atexit one aims to handling process complete successfully.

Now I have a problem I just want release to be invoked only once when the process is killed. Any improvement on my code?

Juliettajuliette answered 5/5, 2014 at 8:27 Comment(3)
I'd like to ask if it's really necessary to exit this way w/o graceful shutdown of the loop in main?Fimbria
A widely used idiom would be to check if we should break the loop and then clearly release resources.Fimbria
@Fimbria Hi, thank you for your fast response. I think yes, the main loop is a http server module in fact, and I have no access to interrupt the loop myself. Only Ctrl-C can stop it. Yes, it's name is bottle T_T.Juliettajuliette
F
18

Well, according to the documentation atexit handlers aren't executed if the program is killed by a signal not handled by Python, or in case of internal error, or if os._exit() is called. So I would use something like this (almost copied your code):

import sys
import signal
import atexit

def release():
    print "Release resources..."

def sigHandler(signo, frame):
    sys.exit(0)

if __name__ == "__main__":
    atexit.register(release)
    signal.signal(signal.SIGTERM, sigHandler)

    while True:
        pass

I've checked release() is called once and only once in case of both TERM (issued externally) and INTR signals (Ctrl-C from keyboard). If you need, you may install more signal handlers (e.g. for HUP etc). If you need "a more graceful shutdown", you should find a way to gracefully break the loop and/or install external "shutdown handlers" (in case of SIGKILL you won't get a chance to cleanly release resources) or simply make your application be ACID.

Fimbria answered 5/5, 2014 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.