threading.Event().wait() is not notified after calling event.set()

我是研究僧i 提交于 2019-12-03 22:28:23

There are several threads discussing related problems with python's threads, interrupts, locks, events.

For example, see here and here, but there are more.

The situation is much better in python3, where the implementation of wait() was improved, to make it intterruptible.

Will this work for you? Basically, start another thread for Listener and wait there while main thread waits for signal.

#!/usr/bin/python
import threading, signal

class Listener(threading.Thread):
    def __init__(self, event):
        super(Listener, self).__init__()
        self.event = event

    def run(self):
        while not self.event.is_set():                                                                                                                                            
            print("Listener started, waiting for messages ...")
            self.event.wait()

        print("Listener is terminated ...")
        self.event.clear()

event = threading.Event()

def handler(signum, frame):
    global event
    event.set()
    print('Signal handler called with signal [%s]' % signum)

if __name__ == "__main__":
    signal.signal(signal.SIGINT, handler)
    listener = Listener(event)
    listener.start()
    while listener.is_alive():
        pass 

The following code is similar to the original.

Differences:

  1. subclass the Thread class, use run (vs start)

  2. use a simple wait() with no timeout, which is more predictable

  3. signal handler doesn't trigger the Event directly. Instead, it just implicitly wakes up the main process, which is sitting on signal.pause().

  4. main proc triggers Event.set() after it wakes up from pause() -- main proc will do this on any signal, not just SIGINT (control-C). For testing purposes, there's an alarm call after two seconds.

Hope this helps!

source

import signal, threading, time

class Listener(threading.Thread):

    def __init__(self, event):        
        super(Listener, self).__init__()
        self.event = event

    def run(self):                
        print("Listener started, waiting for messages ...")    
        while not self.event.wait():
            print('(timeout)')
        print("Listener is terminated ...")
        self.event.clear()    


event = threading.Event()

def handler(signum, _frame):    
    # global event
    # event.set()
    print('Signal handler called with signal [%s]' % signum)

if __name__ == "__main__": 
    signal.signal(signal.SIGINT, handler)
    signal.signal(signal.SIGALRM, handler)
    signal.alarm(2)

    listener = Listener(event)
    listener.start()

    print '* PAUSE'
    signal.pause()              # wait for a signal

    print '* SIGNALLING'
    event.set()
    listener.join()
    print('* DONE')

output

Listener started, waiting for messages ...
* PAUSE
Signal handler called with signal [14]
* SIGNALLING
Listener is terminated ...
* DONE
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!