如何在Windows中自动销毁subprocess?
在C ++ Windows应用程序中,我启动了几个长时间运行的subprocess(目前我使用CreateProcess(…)来执行此操作。
如果我的主进程崩溃或closures,我想要subprocess自动closures。
由于需要这个“父”的崩溃的工作,我相信这需要使用操作系统的某些API /function来完成。 这样所有的“孩子”过程都被清理了。
我该怎么做呢?
Windows API支持称为“作业对象”的对象。 以下代码将创build一个“作业”,该作业被configuration为在主应用程序结束时(清理其句柄时)closures所有进程。 此代码只能运行一次:
HANDLE ghJob = CreateJobObject( NULL, NULL); // GLOBAL if( ghJob == NULL) { ::MessageBox( 0, "Could not create job object", "TEST", MB_OK); } else { JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 }; // Configure all child processes associated with the job to terminate when the jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli))) { ::MessageBox( 0, "Could not SetInformationJobObject", "TEST", MB_OK); } }
然后,当创build每个subprocess时,执行以下代码来启动每个进程的每个subprocess并将其添加到作业对象:
STARTUPINFO info={sizeof(info)}; PROCESS_INFORMATION processInfo; // Launch child process - example is notepad.exe if (::CreateProcess( NULL, "notepad.exe", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo)) { ::MessageBox( 0, "CreateProcess succeeded.", "TEST", MB_OK); if(ghJob) { if(0 == AssignProcessToJobObject( ghJob, processInfo.hProcess)) { ::MessageBox( 0, "Could not AssignProcessToObject", "TEST", MB_OK); } } // Can we free handles now? Not sure about this. //CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); }
VISTA注意:如果您在Vista上遇到访问被拒绝的AssignProcessToObject()问题,请参阅AssignProcessToJobObject在Vista上总是返回“访问被拒绝” 。
一个有点冒失的解决scheme是父进程作为debugging器附加到每个孩子(使用DebugActiveProcess )。 当一个debugging器终止时,它的所有debugging对象进程也被终止。
一个更好的解决scheme(假设你也写了subprocess)应该是让subprocess监视父进程,如果进程退出。
Windows作业对象听起来像一个好地方开始。 作业对象的名称必须是众所周知的,或传递给子代(或inheritance该代码)。 当父母死亡时,孩子们需要注意,无论是通过一个失败的IPC“心跳”,或者只是WFMO / WFSO对父母的进程句柄。 那时候任何一个subprocess都可以把TermianteJobObject拖下来整个组。
您可以保持独立的看门狗进程运行。 它唯一的任务是观察当前的进程空间,以发现你所描述的情况。 它甚至可以在崩溃之后重新启动原始应用程序,或为用户提供不同的选项,收集debugging信息等。只要保持足够简单,以便您不需要第二个监视器就可以观看第一个监视器。
你可能需要保存一个你开始的进程列表,当你退出你的程序的时候,把它们逐个closures。 我不确定在C ++中这样做的具体细节,但它不应该很难。 困难的部分可能是确保subprocess在应用程序崩溃的情况下closures。 .net有能力添加一个函数,当一个未处理的exception发生时被调用。 我不确定C ++是否提供了相同的function。
您可以将每个进程封装在一个C ++对象中,并将其保存在全局范围中。 析构函数可以closures每个进程。 如果程序正常退出,这将工作正常,但它崩溃,所有的投注都closures。
这是一个粗略的例子:
class myprocess { public: myprocess(HANDLE hProcess) : _hProcess(hProcess) { } ~myprocess() { TerminateProcess(_hProcess, 0); } private: HANDLE _hProcess; }; std::list<myprocess> allprocesses;
然后,无论何时启动,请调用allprocessess.push_back(hProcess);
就在我头顶上:
- 你有没有考虑使用线程而不是进程?
- 尝试将主线程/进程的句柄传递给subprocess,并让它们在该句柄上等待。 这适用于线程,因为线程句柄上的等待直到该线程完成并退出。 不太确定它是否适用于进程,应该检查MSDN来validation这一点。