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?
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.