Python - Windows - 当"无关时退出子进程"父母死亡/崩溃

时间:2017-12-05 17:41:02

标签: python windows python-3.x subprocess

经过一些研究,没有明确的答案,如何让子进程了解父进程已经在Windows下死亡/崩溃/退出,这可能使子进程无人值守。有一些建议如下:

始终涉及已经开始生孩子的已知父母。但有些情况下,孩子并不知道这是一个孩子,因为它不是一个孩子,父母也没有努力杀死孩子。

此外,没有父母的控制权。实际案例:

  • Cygwin在Windows下运行
  • 路径中的Windows Python第一
  • 通过setuptools entry_points 工具安装的Python可执行文件。

如上所述,要执行的Python是Windows。 setuptools生成的可执行文件将找到它并使用asocciated脚本作为子进程执行它。

因为一个人在Cygwin下运行,所以可能会失败:

  • Ctrl-c将终止父(存根setuptools可执行文件)
  • 但是会让孩子继续运行(在流程列表中找到python.exe

在这种情况下,如上所述,不可能控制父母,孩子也不会知道孩子(因为它也可能直接作为Python脚本执行)

1 个答案:

答案 0 :(得分:1)

解决方案如下:

import sys

def win_wait_for_parent(raise_exceptions=False):
    if not sys.platform == 'win32':
        return True

    # When started under cygwin, the parent process will die leaving a child
    # hanging around. The process has to be waited upon
    import ctypes
    from ctypes.wintypes import DWORD, BOOL, HANDLE
    import os
    import threading

    INFINITE = -1
    SYNCHRONIZE = 0x00100000

    kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

    kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD)
    kernel32.OpenProcess.restype = HANDLE

    kernel32.WaitForSingleObject.argtypes = (HANDLE, DWORD)
    kernel32.WaitForSingleObject.restype = DWORD

    phandle = kernel32.OpenProcess(SYNCHRONIZE, 0, os.getppid())

    def check_parent():
        # Get a token with right access to parent and wait for it to be
        # signaled (die). Exit ourselves then
            kernel32.WaitForSingleObject(phandle, INFINITE)
            os._exit(0)

    if not phandle:
        if raise_exceptions:
            raise ctypes.WinError(ctypes.get_last_error())

        return False

    threading.Thread(target=check_parent).start()
    return True

如果进程的PID与等待父级的父级的PID(死亡)不同,则在单独的线程中运行。这适用于Python 3.3,其中os.getppid()确实在窗口

下返回父级的PID

它不需要修改父项,并且孩子不需要事先作为孩子进行编码,因为检查了线程必须运行的位置或者没有。

- 重构为函数并添加了注释的改进