I use the following code to handle the SIGINT event. The code sets a multiprocessing.event to "wakeup" the main thread which is waiting.
import multiprocessing
import signal
class Class1(object):
_stop_event = multiprocessing.Event()
@staticmethod
def interrupt():
Class1._stop_event.set()
def wait(self):
print("Waiting for _stop_event")
if Class1._stop_event.wait(5):
print("_stop_event set.")
else:
print("Timed out.")
def stop(signum, frame):
print("Received SIG")
Class1.interrupt()
signal.signal(signal.SIGINT, stop)
c = Class1()
c.wait()
Without any signal, the wait method times out after 10 seconds and the process exits with the following output as expected:
Waiting for _stop_event
Timed out.
When sending the SIGINT signals, the signal gets handled but the event.wait method does not return, neither immediately nor after the timeout. The process never exits. The output is:
Waiting for _stop_event
^CReceived SIG
I can continue to send SIGINTs. The process won't exit and the output is:
Waiting for _stop_event
^CReceived SIG
^CReceived SIG
^CReceived SIG
^CReceived SIG
....
Everything works as expected if I replace the Class1.wait method with a check for event.is_set:
def wait(self):
print("Waiting for _stop_event")
while True:
if Class1._stop_event.is_set():
print("_stop_event set.")
break
The process exits and the output is:
Waiting for _stop_event
^CReceived SIG
_stop_event set.
How to make event.wait return once the event was set? What is the reason that the wait method doesn't even timeout anymore?
You guys are going to like this one. Use threading.Event
, not multiprocessing.Event
. Then when you press ^C
the signal handler is called just like it should!
import threading
import signal
class Class1(object):
_stop_event = threading.Event()
@staticmethod
def interrupt():
Class1._stop_event.set()
def wait(self):
print("Waiting for _stop_event")
if Class1._stop_event.wait(5):
print("_stop_event set.")
else:
print("Timed out.")
def stop(signum, frame):
print("Received SIG")
Class1.interrupt()
signal.signal(signal.SIGINT, stop)
c = Class1()
c.wait()
Waiting for _stop_event
^CReceived SIG
_stop_event set.