delegate SIGINT signal to child process and then cleanup and terminate the parent
Question: I have a main python(testmain.py) script that executes another python
script(test.py) using subprocess.Popen command. When I press Ctrl-C , I want
the child to exit with exit code 2 and then the parent to display that exit
code and then terminate .

I have signal handlers in both parent and child scripts.

testmain.py

    
    
    def signal_handler(signal, frame):
        print "outer signal handler"
        exit(2)
    signal.signal(signal.SIGINT, signal_handler) 
    
    def execute()
    proc=subprocess.Popen("python test.py",shell=True)
        streamdata=proc.communicate()[0]
        rc=proc.returncode
        print "return code:",rc
    
    execute()
    

test.py

    
    
    def signal_handler(signal, frame):
        print "exiting: inner function"
        exit(2)
    signal.signal(signal.SIGINT, signal_handler)
    

I checked [Delegate signal handling to a child process in
python](http://stackoverflow.com/questions/24936107/delegate-signal-handling-
to-a-child-process-in-python) that is kind of similar to my question but in
that case, the parent is continuing it's execution, which I don't want.

I want to: 1.exit test.py with exit(2) 2.print that exit code in testmain.py
3.exit test.py with exit(2)

could someone please provide suggestions to do this? Thanks.

UPDATE : Handling the signal only in the child (test.py) and checking the
return code in parent(testmain.py) will do what I want .

    
    
    if rc==2:
       print "child was terminated"
       exit(2)
    

but I was wondering if there is a clean way to do this using signal handling.


Answer: Your child process shouldn't care what the parent does i.e., if you want the
child to exit with specific status on Ctrl+C then just do that:

    
    
    import sys
    
    try:
        main()
    except KeyboardInterrupt: # use default SIGINT handler
        sys.exit(2)
    

Or you could define the signal handler explicitly:

    
    
    import os
    import signal
    
    def signal_handler(signal, frame):
        os.write(1, b"outer signal handler\n")
        os._exit(2)
    signal.signal(signal.SIGINT, signal_handler)
    main()
    

There might be a difference in behavior if there are `atexit` handlers and/or
multiple threads.

Unrelated: depending on what your `main()` function does, there could be a
significant delay before a signal is handled in Python. Some blocking methods
on Python 2 may ignore the signal completely: use Python 3 or apply a custom
workaround for a specific case e.g., using a timeout parameter for some calls.

* * *

You could handle `SIGINT` in a similar way in the parent:

    
    
    for cmd in commands:
        process = Popen(cmd)
        try:
            process.wait()
        except KeyboardInterrupt:
            # child process may still be alive here
            for _ in range(5): # wait a while
               if process.poll() is not None:
                   break # the process is dead
               time.sleep(.1)
            else: # no break, kill the process explicitly
               try:
                   process.kill()    
               except OSError:
                   pass
            sys.exit("Child exited with %d" % process.wait())
    

Python 2 doesn't restore signals for child processes e.g., if you `SIG_IGN`
the `SIGINT` signal in the parent, [you could reset the necessary hanlders
explicitly using `preexec_fn`
parameter](http://stackoverflow.com/a/22083141/4279).

