在 C++ Windows 应用程序中,我启动了几个长时间运行的子进程(目前我使用 CreateProcess(...) 来执行此操作。
我希望子进程自动关闭如果我的主进程崩溃或已关闭 。
需要解决“父”崩溃的问题,我相信这需要使用操作系统的某些 API/功能来完成,以便清理所有“子”进程
由于 我这样做吗?
In C++ Windows app, I launch several long running child processes (currently I use CreateProcess(...) to do this.
I want the child processes to be automatically closed if my main processes crashes or is closed.
Because of the requirement that this needs to work for a crash of the "parent", I believe this would need to be done using some API/feature of the operating system. So that all the "child" processes are cleaned up.
How do I do this?
发布评论
评论(7)
您可以在创建进程之前将作业分配给父进程:
当作业的最后一个句柄关闭时,
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
会导致与该作业关联的所有进程终止。 默认情况下,所有子进程都会自动分配给作业,除非您在调用CreateProcess
时传递了CREATE_BREAKAWAY_FROM_JOB
。 请参阅 https://learn.microsoft.com/en -us/windows/win32/procthread/process-creation-flags 了解有关CREATE_BREAKAWAY_FROM_JOB
的更多信息。您可以使用 Sysinternals 中的流程资源管理器来确保所有流程都分配给该作业。 像这样:
You can assign a job to the parent process before creating processes:
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
causes all processes associated with the job to terminate when the last handle to the job is closed. By default, all child processes will be assigned to the job automatically, unless you passedCREATE_BREAKAWAY_FROM_JOB
when callingCreateProcess
. See https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags for more information aboutCREATE_BREAKAWAY_FROM_JOB
.You can use process explorer from Sysinternals to make sure all processes are assigned to the job. Just like this:
Windows 作业对象听起来是一个不错的起点。 作业对象的名称必须是众所周知的,或者传递给子对象(或继承句柄)。 当父进程死亡时,子进程需要得到通知,无论是通过失败的 IPC“心跳”还是仅通过父进程句柄上的 WFMO/WFSO。 此时,任何子进程都可以通过 TermianteJobObject 来破坏整个组。
Windows Job Objects sounds like a good place to start. The name of the Job Object would have to be well-known, or passed to the children (or inherit the handle). The children would need to be notice when the parent dies, either through a failed IPC "heartbeat" or just WFMO/WFSO on the parent's process handle. At that point any child process could TermianteJobObject to bring down the whole group.
一种有点黑客的解决方案是让父进程作为调试器附加到每个子进程(使用 DebugActiveProcess)。 当调试器终止时,其所有被调试进程也会终止。
更好的解决方案(假设您也编写了子进程)是让子进程监视父进程,并在父进程消失时退出。
One somewhat hackish solution would be for the parent process to attach to each child as a debugger (use DebugActiveProcess). When a debugger terminates all its debuggee processes are terminated as well.
A better solution (assuming you wrote the child processes as well) would be to have the child processes monitor the parent and exit if it goes away.
您可以将每个进程封装在一个 C++ 对象中,并在全局范围内保留它们的列表。 析构函数可以关闭每个进程。 如果程序正常退出,那会工作得很好,但如果它崩溃了,所有的赌注都会被取消。
这是一个粗略的例子:
然后每当你启动一个进程时,调用 allprocessess.push_back(hProcess);
You could encapsulate each process in a C++ object and keep a list of them in global scope. The destructors can shut down each process. That will work fine if the program exits normally but it it crashes, all bets are off.
Here is a rough example:
Then whenever you launch one, call allprocessess.push_back(hProcess);
您可能必须保留您启动的进程的列表,并在退出程序时将它们一一杀死。 我不确定在 C++ 中执行此操作的具体细节,但这应该不难。 困难的部分可能是确保在应用程序崩溃时关闭子进程。 .Net 能够添加一个在发生未处理异常时调用的函数。 我不确定 C++ 是否提供相同的功能。
You'd probably have to keep a list of the processes you start, and kill them off one by one when you exit your program. I'm not sure of the specifics of doing this in C++ but it shouldn't be hard. The difficult part would probably be ensuring that child processes are shutdown in the case of an application crash. .Net has the ability to add a function that get's called when an unhandled exception occurs. I'm not sure if C++ offers the same capabilities.
您可以保持单独的看门狗进程运行。 它唯一的任务是观察当前的进程空间以发现您所描述的情况。 它甚至可以在崩溃后重新启动原始应用程序,或者为用户提供不同的选项,收集调试信息等。只要尽量保持足够简单,这样您就不需要第二个看门狗来监视第一个看门狗。
You can keep a separate watchdog process running. Its only task is watching the current process space to spot situations like you describe. It could even re-launch the original application after a crash or provide different options to the user, collect debug information, etc. Just try to keep it simple enough so that you don't need a second watchdog to watch the first one.
Windows API 支持称为“作业对象”的对象。 以下代码将创建一个“作业”,配置为在主应用程序结束时(当其句柄被清理时)关闭所有进程。 此代码应该只运行一次。:
然后,当创建每个子进程时,执行以下代码来启动每个子进程并将其添加到作业对象中:
VISTA 注意:请参阅 如果您遇到访问权限,AssignProcessToJobObject 在 Vista 上始终返回“访问被拒绝”拒绝在 Vista 上使用 AssignProcessToObject() 的问题。
The Windows API supports objects called "Job Objects". The following code will create a "job" that is configured to shut down all processes when the main application ends (when its handles are cleaned up). This code should only be run once.:
Then when each child process is created, execute the following code to launch each child each process and add it to the job object:
VISTA NOTE: See AssignProcessToJobObject always return "access denied" on Vista if you encounter access-denied issues with AssignProcessToObject() on vista.