Reputation: 920
I have a script that I was trying to add a signal handler for ctr-c, to do some final handling before exiting.
On it's own, it works fine but as soon as I try it in my program, it doesn't work. Adding or removing an import seems to change the behavior.
Without the P4API import, it works as I expect. If I do import P4API, ctr-c seems to call exit or bypass my handler, and I'm not sure why, or how to track what is changing.
import signal
import time
import sys
# -- with this commented out, things work
#import P4API
def run_program():
while True:
time.sleep(1)
print("a")
def exit_gracefully(signum, frame):
# restore the original signal handler as otherwise evil things will happen
# in raw_input when CTRL+C is pressed, and our signal handler is not re-entrant
signal.signal(signal.SIGINT, original_sigint)
try:
if raw_input("\nReally quit? (y/n)> ").lower().startswith('y'):
sys.exit(1)
except KeyboardInterrupt:
print("Ok ok, quitting")
sys.exit(1)
# restore the exit gracefully handler here
signal.signal(signal.SIGINT, exit_gracefully)
if __name__ == '__main__':
# store the original SIGINT handler
original_sigint = signal.getsignal(signal.SIGINT)
signal.signal(signal.SIGINT, exit_gracefully)
run_program()
Upvotes: 3
Views: 94
Reputation: 365707
According to the documentation, p4api has a class called Signaler
that it uses for "interrupt handling":
The
Signaler
class enables the API programmer to register functions that are to be called when the client application receives an interrupt signal. TheSignaler
class maintains a list of registered functions and calls each one in turn.By default, after all of the registered functions have been executed, the process exits, returning -1 to the operating system.
Presumably it installs this when you import p4api
. So, your signal handler is interfering with its signal handler, and ultimately it's stealing the signal and calling _exit(-1)
or similar before you get a chance to do anything useful.
You can find the details here, but it looks like Signaler::OnIntr
is the C++ name of the function you want to call to register with its signal handler. There's example code in the docs, too. The first Google search result gives me this C++ source, which makes it pretty clear that's correct.
I don't see anything in the Python API docs, and I don't know if the Python API is a wrapper around the C++ API, or a separate implementation, but either way I'm guessing it has a class with a similar name that you have to use in the same way.
Upvotes: 2