Popen发送信号,子进程未收到信号

4
我正在使用subprocess.Popen运行多个进程,当检测到一组文件中的任何更改时,我想向这些进程中的一个发送信号。 我在进程中定义了信号处理程序,但似乎没有收到任何信号。 希望能得到一些帮助。 下面显示了发送信号的函数和信号处理程序。
def start_up():
    p, i = None, None
    while 1:
        subprocess.call(['clear'])
        logging.info('starting overlay on host %s' % socket.gethostname())
        p = subprocess.Popen([sys.executable, 'sdp_proc.py'])
        i = subprocess.Popen([sys.executable, 'kernel.py', sys.argv[1],
                                 sys.argv[2]])
        if file_modified():
            p.terminate()
            i.send_signal(signal.SIGINT)
        time.sleep(1)

下面是信号处理程序的示例:
def signal_handler(signum, frame):
    with open('log.txt', 'w') as f:
        f.write(' so what mate, received signal with signal number %s' % signum)


signal.signal(signal.SIGINT, signal_handler)

sdp_proc.pykernel.py是做什么的?它们会一直运行还是在1秒钟后结束?另外,我将使用open('log.txt', 'a')打开日志文件以追加消息。 - twil
2个回答

2
我猜测在子进程加载完所有Python之前就会发送SIGINT信号,因此在安装SIGINT处理程序之前,它将立即死亡。
您可能希望监视子进程以满足某些成功加载条件(例如只需在管道上发送一个字节),然后再发送任何您希望由自己的处理程序代码处理的SIGINT信号。

0
根据Unix和NT的官方文档,如果使用shell=True,则需要使用进程组来接收信号。
因此,我决定包装内置的Popen函数以实现这种行为。
import subprocess as sp
import os

def Popen(command, env=None, **kw):
    if os.name == 'nt':
        # On Windows, the specified env must include a valid SystemRoot
        # Use a current value
        if env is None:
            env = {}

        env['SystemRoot'] = os.environ['SystemRoot']
        kw['creationflags'] = sp.CREATE_NEW_PROCESS_GROUP
    else:
        kw['preexec_fn'] = os.setpgrp

    return sp.Popen(command, env=env, **kw)

跨平台的kill函数:
if os.name == 'nt':
    # On Windows, os module can't kill processes by group
    # Kill all children indiscriminately instead
    def killpg_by_pid(pid, s):
        # Ignoring s due the lack of support in windows.j
        sp.call(['taskkill', '/T', '/F', '/PID', str(pid)])

else:

    def killpg_by_pid(pid, s):
        os.killpg(os.getpgid(pid), s)

使用方法:

已在Linux和Windows系统中测试通过。

import signal

process = Popen(
    command,
    stdout=sp.PIPE,
    stderr=sp.PIPE,
    shell=True,
    **kw,
)

# Kill
killpg_by_pid(process.pid, signal.SIGTERM)

完整的示例请参考:bddcli


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接