Why does using threading.Event result in SIGTERM not being caught?

前端 未结 2 353
悲哀的现实
悲哀的现实 2020-12-17 14:37

I have a threaded Python daemon. Like any good daemon, it wants to launch all of its worker threads, then wait around until it\'s told to terminate. The normal signal for te

相关标签:
2条回答
  • 2020-12-17 15:04

    From Python documentation on signals:

    Although Python signal handlers are called asynchronously as far as the Python user is concerned, they can only occur between the “atomic” instructions of the Python interpreter. This means that signals arriving during long calculations implemented purely in C (such as regular expression matches on large bodies of text) may be delayed for an arbitrary amount of time.

    I tested various threading and thread classes and none of them work the way you want it -- this is probably because of how Python handles signals.

    In signal, however, there is a pause() function that sleeps until a signal is received by the process. Your modified example would look like this:

    import signal
    
    RUN = True
    
    def handle(a, b):
        global RUN
        print "handled"
        RUN = False
    
    signal.signal(signal.SIGTERM, handle)
    signal.signal(signal.SIGINT, handle)
    signal.signal(signal.SIGHUP, handle)
    
    while RUN:
        signal.pause()
    
    print "Stopping"
    

    I checked it on Linux, it works. I don't think it classifies as poll-and-sleep anymore if your application doesn't use a lot of other signals.

    It's good to handle SIGINT and SIGHUP too, to properly handle user interruption (usually by pressing Ctrl+C) and user disconnection (closing the parent terminal) respectively.

    Also, note that signal.pause() is not available on Windows systems.

    0 讨论(0)
  • 2020-12-17 15:20

    In Python 3, this works:

    from threading import Event
    from os import getpid
    from signal import SIGTERM, SIGINT, SIGHUP, signal
    
    stop_event = Event()
    
    def handler(signum, frame):
        stop_event.set()
    
    def main():
        signal(SIGTERM, handler)
        signal(SIGINT, handler)
        signal(SIGHUP, handler)
        print('start, pid:', getpid())
        stop_event.wait()
        print('done')
    
    if __name__ == '__main__':
        main()
    

    It looks that in Python 2.7 it works only if you specify wait interval: stop_event.wait(number_of_seconds)

    0 讨论(0)
提交回复
热议问题