ρss
ρss

Reputation: 5315

How are different signals handled in python

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

Answers (2)

Alp
Alp

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

dstromberg
dstromberg

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

Related Questions