delegate SIGINT signal to child process and then cleanup and terminate the parent

老子叫甜甜 提交于 2019-12-11 02:59:44

问题


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 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.


回答1:


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.



来源:https://stackoverflow.com/questions/32487700/delegate-sigint-signal-to-child-process-and-then-cleanup-and-terminate-the-paren

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!