从子进程接收时如何处理SIGTERM。在多进程中的工作进程上打开Popen进程而不终止进程树

时间:2018-10-04 08:51:01

标签: python multiprocessing subprocess python-3.6 signal-handling

我有一个python脚本,它创建多进程进程,每个进程工作人员都使用subprocess.Popen使用linux数据库实用程序运行一些数据库操作。有时,数据库实用程序会发送SIGTERM。如何处理来自linux命令的SIGTERM,而不终止整个进程树以及当前的进程工作器?

到目前为止,我的代码:

import multiprocessing as mp
import subprocess
import shlex
import signal

class SigTermError(Exception):
    pass

def sig_handler(sig, frame):
    raise SigTermError( ("Received Signal:{} "
                     "on line:{} in file:{}")
                    .format(str(sig)
                            , str(frame.f_lineno)
                            , frame.f_code.co_filename))

def do_something_to_hanlde_sigterm():
    print('Handled SIGTERM')

def move_on():
    print('Moving on')



def run_shell_command(cmd_string):
    """ Run a shell command"""
    original_sigterm_handler = signal.getsignal(signal.SIGTERM)
    signal.signal(signal.SIGTERM, sig_handler)
    args = shlex.split(cmd_string)

    # I want to handle the SIGTERM and if the cmd_string sends a SIGTERM then return a ret_code of -99
    try:
        p = subprocess.Popen(args, shell=False
                             , stdout=subprocess.PIPE
                             , stderr=subprocess.PIPE
                             )


        out, err = p.communicate() # This fails if the cmd_string sends a SIGTERM

        ret_code = p.returncode
    except SigTermError:
        ret_code = -99
    finally:
        signal.signal(signal.SIGTERM, original_sigterm_handler)
        return ret_code


def worker(arg1, arg2):
    """ Run db_command with 2 arguments. """
    cmd_string = 'db_command -parameter1 {arg1} -parameter2 {arg2}'.format(arg1=arg1,arg2=arg2)
    func_return = run_shell_command(cmd_string)  # The whole process tree terminates if subprocess sends sigterm
    if func_return == -99:
        do_something_to_hanlde_sigterm()
    else:
        move_on()

if __name__ == '__main__':

    processes = [mp.Process(target=worker, args=(x, x*x)) for x in list(range(4))]

    for p in processes:
        p.start()

    for p in processes:
        p.join()

    print('All Done')

0 个答案:

没有答案