Reputation: 5315
I am using python 2.7 version on ubuntu. I am curious regarding how different signals are handled in python program during its execution. Is there any priority based selection.? For eg: If there are two different signals generated at the same time, which one will be served first? In my program given below it waits for the user to press Ctrl-C key, if done so it will display "Process can't be killed with ctrl-c key!". Along with this it keep generating an SIGALRM signal every second and keeps generating "Got an alarm" message in output every second.
#!/usr/bin/env python
import signal
import time
def ctrlc_catcher(signum, frm):
print "Process can't be killed with ctrl-c!"
def alarm_catcher(signum,frame):
print "Got an alarm"
signal.signal(signal.SIGINT, ctrlc_catcher)
signal.signal(signal.SIGALRM, alarm_catcher)
while True:
signal.alarm(1)
time.sleep(1)
pass
Now when I execute the programme it produces following output indefinitely:
Got an alarm
Got an alarm
Got an alarm
Got an alarm
If during the execution I hit Ctrl-C key once then the output is interrupted and as shown below:
Got an alarm
Got an alarm
Got an alarm
Got an alarm
Process can't be killed with ctrl-c
Got an alarm
Everything is working as programmed and as expected. My question is if I press the ctrl-c key continuously then why the output is as given below:
Process can't be killed with ctrl-c
Process can't be killed with ctrl-c
Process can't be killed with ctrl-c
Why isn't the output regarding the triggering of alarm also shows up in the above output as the alarm is being triggered every second? Is the alarm signal (signal.ALARM) being ignored because of signal.SIGNIT? Or the continuous pressing of Ctrl-C key is pausing something? Thanks
Upvotes: 2
Views: 1230
Reputation: 2826
The behavior you see is due to the interaction of two factors:
(1) When you call signal.alarm
, you clear any previous alarms; after the call, only the most recently requested alarm is scheduled.
(2) A caught signal terminates time.sleep
and causes the sleep to be cut short; it does not resume after the signal handler returns.
Now, when you send SIGINT
to your process, it usually arrives during the sleep, which it interrupts, and so after your handler ctlc_catcher
returns the while
loop immediately continues to the next iteration, scheduling a new alarm for one second from that point and clearing any old alarms. In other words, if SIGINT
arrives during an iteration of the loop, that iteration will almost never end up sleeping for a full second, and so the next iteration of the loop will execute and clear the already scheduled alarm before it has a chance to be delivered.
It follows from this that if you press cntl-C more frequently than once per second, you won't see "Got an alarm."
at all.
If you want to guarantee that an alarm is delivered once per second despite any interrupts, you'll have to do some extra work to decide, on each loop iteration, whether you should schedule an alarm.
Upvotes: 4
Reputation: 7167
Perhaps something like this?
#!/usr/local/cpython-3.3/bin/python
import subprocess
p = subprocess.Popen("./app",
stdin = subprocess.PIPE,
stdout = subprocess.PIPE,
stderr = subprocess.PIPE,
shell = True)
p.stdin.write(bytes("3\n", "ascii"))
p.stdin.write(bytes("4\n", "ascii"))
print(p.stdout.read())
exit_code = p.wait()
print(exit_code)
Upvotes: 0