【问题标题】:CreateProcess such that child process is killed when parent is killed?CreateProcess 这样子进程在父进程被杀死时被杀死?
【发布时间】:2011-09-09 16:26:28
【问题描述】:

有没有办法调用CreateProcess,这样杀死父进程就会自动杀死子进程?

也许使用Create Process Flags

编辑
解决方案是创建一个作业对象,将父级和子级都放在作业对象中。当他的父母被杀时,孩子也被杀了。我从这里得到了代码: Kill child process when parent process is killed 注意@wilx 关于继承句柄的评论。

【问题讨论】:

    标签: c++ winapi process kernel32 win32-process


    【解决方案1】:

    Neil says 的身份使用工作是恕我直言的最佳方式。通过使用SetInformationJobObject() 在作业对象上设置JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,您可以使子进程在拥有作业的进程终止时被杀死。当您的父进程退出/死亡时,作业对象句柄将关闭。为此,作业句柄被子进程继承是很重要的。如果您还想跟踪孙子进程,则必须创建暂停的子进程,将它们添加到您的作业对象中,然后才让它们运行。

    【讨论】:

    • +1,谢谢!幸运的是,我用来创建子进程的库没有继承作业句柄,所以效果很好。
    【解决方案2】:

    你能做的最好的是将两个进程放在同一个作业中,这样杀死作业就会杀死两个进程。

    【讨论】:

    • @Neil - 我可以在它们启动后将它们放在同一个作业中吗?
    • @SFun28 我认为 AssignProcessToJobObject 可能是你需要的。
    • @SFun28:是的——CreateJobObjectAssignProcessToJobObject
    • @Jerry/Neil - 试过了。我确认我得到了一个作业句柄,并且将进程分配给作业成功,但是杀死一个进程并不会杀死另一个进程。也许我做错了什么。
    • @SFun28:在这种情况下,杀死父进程不会自动杀死子进程。父进程在退出时必须调用 TerminateJobObject 以杀死作业对象中的其他进程。
    【解决方案3】:

    您需要子进程被杀死,还是仅仅检测父进程退出以便它可以干净地终止?父进程可以为自己创建一个可继承的句柄,然后子进程可以将其与自己的对象一起传递给WaitForMultipleObjects(Ex)

    如果子进程不是专门为此编写的,您可以将其标准输入附加到管道,该管道的另一端由父进程持有。如果父节点死亡,管道会自动关闭。

    这与 Unix 行为非常相似,其中子代在其父代死亡时不会被杀死,它通常会在响应SIGHUP 时退出(但它可以处理该信号并实现任何行为)。在 Linux 上,孤儿的父 PID 更改为 1 (init)。

    【讨论】:

    • @Ben - 好问题!我需要杀死子进程。我不拥有子进程,因为它不是我的源代码,所以我不能以任何方式定制子进程。
    • 使用标准输入的好主意...可能比我的技能水平高一点。最终,我通过 .net pinvoke 完成了所有 Win32 Api 的工作。
    • @SFun28:.NET 使重定向标准输入非常简单,只需使用 System.Diagnostics.Process 类并在调用 Process.Start 时使用 the RedirectStandardInput option
    • @Ben - 我会,但我没有启动进程 =) 我可以通过 pid 获取 Process 对象,但我的理解是我无法访问标准输入(我知道我不为标准输出/错误)
    • @SFun28:如果您的程序没有启动子进程,我不确定您所说的“父”和“子”是什么意思。既然你问的是CreateProcess,我很确定你正在启动子进程。
    【解决方案4】:

    我想DEBUG_PROCESSDEBUG_ONLY_THIS_PROCESS 会这样做几乎是意外的副作用。 Windows 不像类 Unix 系统那样在树中创建进程。

    【讨论】:

    • 我试过这个,它似乎暂停了子进程。而之前我在同一个控制台窗口中看到子进程的标准输出,现在我什么也看不到。也许我需要结合其他一些标志?
    • @SFun28:这(可能)不是另一个标志的问题,而是在父级中放置一个小循环,调用WaitForDebugEventContinueDebugEvent 以便孩子可以运行直到你决定杀死它。
    • 这越来越乱了......似乎从 .net 调用调试 API 的最佳方法是使用这个:blogs.msdn.com/b/jmstall/archive/2006/11/22/…
    • @SFun28:是的,从 .NET 来看,这可能是/将会是一种痛苦。
    • 感谢您的建议。我最终放弃了这种方法,转而采用我现在正在使用的 Job 方法。感谢您的所有帮助。
    【解决方案5】:

    另一种方法

    所有情况下都没有用,但是我有一个特殊的场景,应用程序完全控制了一个子进程。对于通信和 API 拦截,需要 DLL 注入,以便 DLL 在实际子进程中运行以向父进程报告。

    注意:现在,这不是创意奖。 这里的背景是: 需要包装的应用程序,但它是一个遗留应用程序,既不能修改,也不能以令人满意的方式重写。我们需要保持这个系统运行,同时仍然截取它的输出。

    另外,子进程写得不好,它会立即重新启动然后终止,所以父进程实际上不是我们的主应用程序。

    如果您控制子进程并且有一个注入的 DLL,您可以扩展此 DLL,方法是监视父进程以检查它是否正在运行。如果没有,ExitProcess

    如果您不需要子进程中的 DLL,则其他解决方案很可能要好得多。


    您可以通过例如您的应用程序已经使用的注册表项来传输parentProcessID。或者你可以传递一个命令行,如果这不会破坏子进程。

    这必须在它自己的线程中运行。我的 DLL 有两个线程:这里的代码和控制和通信代码。

    DLL

    bool IsProcessRunning(HANDLE hProcess)
    {
        DWORD exitCode;
        GetExitCodeProcess(hProcess, &exitCode);
        return exitCode == STILL_ACTIVE;
    }
    
    bool WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved)
    {
        if (fdwReason == DLL_PROCESS_ATTACH)
        {
            int parentProcessID = [...]
            
            HANDLE parentProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, parentProcessID);
            while (IsProcessRunning(parentHandle)) Sleep(100);
            ExitProcess(0);
        }
    
        return true;
    }
    

    【讨论】:

      【解决方案6】:

      不知道 windows,但这将在 linux 上运行: prctl(PR_SET_PDEATHSIG, SIGHUP);

      【讨论】:

      • 请注意:这应该在子进程中调用。
      猜你喜欢
      • 1970-01-01
      • 2010-12-08
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多