如何在子进程中启动崩溃(很少)应用程序 [英] How to launch crashing (rarely) application in subprocess

查看:578
本文介绍了如何在子进程中启动崩溃(很少)应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个python应用程序需要执行专有应用程序(它会不时崩溃)每天大约20 000次。

I'm having python application which needs to execute proprietary application (which crashes from time to time) about 20 000 times a day.

问题是当应用程序崩溃,Windows会自动触发 WerFault ,这将使程序挂起,因此< a href =http://docs.python.org/2/library/subprocess.html#subprocess.call> python的 subprocess.call() 将永远等待用户输入(该应用程序必须在周末,节假日,每天24小时运行...因此这是不能接受的)。

The problem is when application crashes, Windows automatically triggers WerFault which will keep program hanging, thus python's subprocess.call() will wait forever for user input (that application has to run on weekends, on holidays, 24/7... so this is not acceptable).

如果使用 sleep;轮询;杀;终止,但这意味着丢失使用 communicate()的能力,应用程序可以运行从几毫秒到2小时,因此设置固定超时将无效

If though about using sleep; poll; kill; terminate but that would mean losing ability to use communicate(), application can run from few miliseconds to 2 hours, so setting fixed timeout will be ineffective

我也尝试过打开自动调试(使用脚本将采取应用程序的崩溃转储和终止ID),但不知何故这个 howto 不能在我的服务器上工作(WerFault仍然出现并等待用户输入)。

I also tried turning on automatic debugging (use a script which would take a crash dump of an application and terminate id), but somehow this howto doesn't work on my server (WerFault still appears and waits for user input).

其他一些教程,如也没有任何效果。

Several other tutorials like this didn't take any effect either.

问题
有一种方法如何防止WerFault显示(等待用户输入)? 这是更多的系统然后编程问题

替代问题:是有一个优雅方法在python如何检测应用程序崩溃(无论是否显示WerFault )

推荐答案

)回答,不时监视 WerFault.exe 实例,特别是与违规的 PID 相关联的实例应用。杀了它。处理 WerFault.exe 很复杂,但您不想禁用它 - 请参阅 Windows错误报告服务。

Simple (and ugly) answer, monitor for WerFault.exe instances from time to time, specially the one associated with the PID of the offending application. And kill it. Dealing with WerFault.exe is complicated but you don't want to disable it -- see Windows Error Reporting service.


  1. 获取按照名称匹配 WerFault.exe 的进程列表。我使用 psutil 包。请小心 psutil ,因为进程已缓存,请使用 psutil.get_pid_list()

  2. 使用 argparse 解码其命令行。这可能是过度的,但它利用现有的Python库。

  3. 根据 PID 识别持有应用程序的进程。 li>
  1. Get a list of processes by name that match WerFault.exe. I use psutil package. Be careful with psutil because processes are cached, use psutil.get_pid_list().
  2. Decode its command line by using argparse. This might be overkill but it leverages existing python libraries.
  3. Identify the process that is holding your application according to its PID.

这是一个简单的实现。

def kill_proc_kidnapper(self, child_pid, kidnapper_name='WerFault.exe'):
    """
    Look among all instances of 'WerFault.exe' process for an specific one
    that took control of another faulting process.
    When 'WerFault.exe' is launched it is specified the PID using -p argument:

    'C:\\Windows\\SysWOW64\\WerFault.exe -u -p 5012 -s 68'
                             |               |
                             +-> kidnapper   +-> child_pid

    Function uses `argparse` to properly decode process command line and get
    PID. If PID matches `child_pid` then we have found the correct parent
    process and can kill it.
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-u', action='store_false', help='User name')
    parser.add_argument('-p', type=int, help='Process ID')
    parser.add_argument('-s', help='??')

    kidnapper_p = None
    child_p = None

    for proc in psutil.get_pid_list():
        if kidnapper_name in proc.name:
            args, unknown_args = parser.parse_known_args(proc.cmdline)
            print proc.name, proc.cmdline

            if args.p == child_pid:
                # We found the kidnapper, aim.
                print 'kidnapper found: {0}'.format(proc.pid)
                kidnapper_p = proc

    if psutil.pid_exists(child_pid):
        child_p = psutil.Process(child_pid)

    if kidnapper_p and child_pid:
        print 'Killing "{0}" ({1}) that kidnapped "{2}" ({3})'.format(
            kidnapper_p.name, kidnapper_p.pid, child_p.name, child_p.pid)
        self.taskkill(kidnapper_p.pid)
        return 1
    else:
        if not kidnapper_p:
            print 'Kidnapper process "{0}" not found'.format(kidnapper_name)
        if not child_p:
            print 'Child process "({0})" not found'.format(child_pid)

    return 0

现在, taskkill 函数使用正确的 PID 调用 taskkill commmand。

Now, taskkill function invokes taskkill commmand with correct PID.

def taskkill(self, pid):
    """
    Kill task and entire process tree for this process
    """
    print('Task kill for PID {0}'.format(pid))
    cmd = 'taskkill /f /t /pid {0}'.format(pid)
    subprocess.call(cmd.split())

这篇关于如何在子进程中启动崩溃(很少)应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆