Search code examples
python-3.xlinuxsignals

Handling USR1 signals in python


I'm still new to signals in python and I want to know what is wrong with my program here.

I have prog1.py :

import signal 
import os
import time


pid = os.getpid()

def receive(signum, stack):
    print("Received",signum)

signal.signal(signal.SIGUSR1, receive)

print("PID is : ",pid)

while True:
    print("Waiting")
    time.sleep(3)

And prog2.py :

from prog1 import pid

n = 0

while True:
    n = n + 1
    print(n)
    if ( n % 10 == 0):
        os.kill(pid, signal.SIGUSR1)

So what I want to do here is send a USR1 signal to prog1.py every time n is divisible by 10.

So first I run prog1.py so I can extract its pid and pass it to prog2. Then I run prog2.py to get prog1's pid and send a USR1 signal to prog1 every time n is divisible by 10. But what happens here is different : After running prog1 I get this output (which is excepted):

PID is :  15355
Waiting
Waiting
Waiting
Waiting
...

But when I run prog2, I get this output (which I didn't expect):

PID is :  15629
Waiting
Waiting
Waiting
Waiting
...

What am I doing wrong here ?


Solution

  • If you don't want to fork prog1.py from prog2.py but run them independently you have to save PID of prog1.py somewhere on the filesystem and make prog2.py read it. Additionally, you'll quickly learn that running print() in signal handler is a bad idea - signal handlers should be very fast and run reentrant functions. At the end of the day, code could look like this:

    prog1.py:

    #!/usr/bin/env python3
    
    import signal
    import os
    import time
    
    
    pid = os.getpid()
    
    with open("/tmp/prog1.pid", "w") as pidfile:
        pidfile.write(f"{pid}\n")
    
    GOT = 0
    
    
    def receive(signum, stack):
        global GOT
        GOT = 1
    
    
    signal.signal(signal.SIGUSR1, receive)
    
    print("PID is : ", pid)
    
    while True:
        if GOT == 1:
            print("Received signal.SIGUSR1")
            GOT = 0
    
        print("Waiting")
        time.sleep(3)
    

    prog2.py:

    #!/usr/bin/env python3
    
    import os
    import signal
    
    with open("/tmp/prog1.pid", "r") as pidfile:
        prog1_pid = int(pidfile.readline())
    
    N = 0
    
    while True:
        N = N + 1
        if N % 10 == 0:
            os.kill(prog1_pid, signal.SIGUSR1)