alvinzoo
alvinzoo

Reputation: 513

signal handler not working in python

I am writing an asynchronous video playing program on Raspberry Pi. I need to run omxplayer in a subprocess and receive input in main process. When some input is received, main process would send the signal to the subprocess.

Here is my code:

def worker():
    p = subprocess.Popen(['omxplayer', '1.mov'], stdin = subprocess.PIPE)
    def handler(signum, frame):
        print p.pid
        p.stdin.write('q') # keystroke of 'q' will quit omxplayer FYI
    signal.signal(signal.SIGUSR1, handler) # can only be trigger in code

So far it seems fine. I can run worker() and send SIGUSR1 in a code snippet and it works fine. Like this:

def test():
    worker()
    time.sleep(5)
    os.kill(int(os.getpid()), signal.SIGUSR1)

But when I try to start worker as a multiprocess, it seems the process cannot receive the signal.

def main_process():
    w = multiprocessing.Process(target=worker)
    w.start()
    time.sleep(5)
    os.kill(w.pid, signal.SIGUSR1)

The handler will not be called in this way. Which part is probably wrong? The signal is not received, or the binding is not right?

I think os.kill is not working as I thought. The signal is not received at all. How to fix this?

Upvotes: 2

Views: 2791

Answers (1)

noxdafox
noxdafox

Reputation: 15040

According to the code you posted, the worker will call Popen set the signal handler and then it will exit.

The subsequent call to os.kill in your code will send the signal to an already expired process.

In general, it's better not to use signals to communicate between processes but rather using Pipe or Queue.

The following example is more robust and flexible as it allows you to send different commands to the worker.

import subprocess
import multiprocessing

def worker(queue):
    p = subprocess.Popen(['omxplayer', '1.mov'], stdin = subprocess.PIPE)

    while 1:
         message = queue.get()  # blocks until new message
         p.stdin.write(message)

def main():
    queue = multiprocessing.Queue()
    w = multiprocessing.Process(target=worker, args=(queue,))
    w.start()
    queue.put('q')

Upvotes: 2

Related Questions