当孩子被杀时,防止线程subprocess.popen终止我的主脚本?

时间:2013-03-12 01:28:09

标签: multithreading python-2.7 signals subprocess parent-child

Solaris 10上的Python 2.7.3

问题

  1. 当我的子进程有内部分段错误(核心)问题或者用户使用SIGTERM或SIGKILL从shell外部杀死它时,我的主程序的信号处理程序处理SIGTERM(-15)和我的父程序退出。 这是真的吗?或者它是一个糟糕的python构建?
  2. 背景和代码

    我有一个首先生成工作管理线程的python脚本。然后,工作线程管理线程生成一个或多个工作线程。我的主线程中还有其他一些我无法阻止的东西。我的管理线程和工作线程是坚如磐石的。我的服务运行多年没有重新启动,但我们有subprocess.Popen方案:

    在工作线程的run方法中,我正在使用:

    class workerThread(threading.Thread):
        def __init__(self) :
            super(workerThread, self).__init__()
        ...
        def run(self)
            ...
            atempfile = tempfile.NamedTempFile(delete=False)
    
            myprocess = subprocess.Popen( ['third-party-cmd', 'with', 'arguments'],  shell=False, stdin=subprocess.PIPE, stdout=atempfile, stderr=subprocess.STDOUT,close_fds=True)
            ...
    

    我需要使用myprocess.poll()来检查进程终止,因为我需要扫描atempfile,直到找到相关信息(文件可能> 1 GiB)并且我需要终止进程因为用户请求或因为进程运行时间过长。一旦找到我要找的东西,我就会停止检查stdout临时文件。我将在外部进程停止并且工作线程终止之前将其清理干净。我需要stdin PIPE,以防我需要在孩子的stdin流中注入一些交互式的响应。

    在我的主程序中,如果我的主python程序使用SIGTERM或SIGINT(Ctrl-C)终止(如果从shell运行),我为我设置一个SIGINT和SIGTERM处理程序来执行清理。

    有没有人有一个坚实的2.x配方用于线程中的子信号处理? ctypes sigprocmask等。

    非常感谢任何帮助。我只是在寻找一位官员'食谱或最佳黑客,如果有的话。

    备注

    我正在使用受限制的Python构建。我必须使用2.7.3。第三方cmd是我没有源代码的程序 - 修改它是不可能的。

1 个答案:

答案 0 :(得分:1)

你的描述中有很多东西看起来很奇怪。首先,您有几个不同的线程和进程。谁崩溃,谁接收SIGTERM,谁接收SIGKILL以及由于哪些操作?

第二:为什么你的父母会收到SIGTERM?它无法隐式发送。有人直接或间接地向您的父进程调用kill(例如,通过终止整个父组)。

第三点:当您处理SIGTERM时,您的程序如何终止?根据定义,如果没有处理,程序将终止。如果它被处理,它不会被终止。真的发生了什么?

建议:

    $ cat crsh.c
    #include <stdio.h>

    int main(void)
    {
        int *f = 0x0;

        puts("Crashing");
        *f = 0;
        puts("Crashed");
        return 0;
    }
    $ cat a.py

    import subprocess, sys

    print('begin')
    p = subprocess.Popen('./crsh')
    a = raw_input()
    print(a)
    p.wait()
    print('end')
    $ python a.py 
    begin
    Crashing
    abcd
    abcd
    end

这很有效。没有信号传递给父母。你有没有在程序中找出问题?

如果问题是发送到多个进程的信号:您是否可以使用setpgid为子进程设置单独的进程组?

是否有任何理由创建临时文件?它是在临时目录中创建的1 GB文件。为什么不管道stdout?

如果您确定需要在父程序中处理信号(为什么不尝试/除了KeyboardInterrupt,例如?):可能使用多线程程序发出信号()未指定的行为会导致这些问题(对于例如,将信号分派给不处理信号的线程??

NOTES
     The effects of signal() in a multithreaded process are unspecified.

无论如何,尝试更精确地解释你的程序的线程和过程是什么,他们做了什么,信号处理程序是如何设置的,为什么,谁在发送信号,谁在接收等等,等等。