문제

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top