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?
The solution is to use "job objects" http://msdn.microsoft.com/en-us/library/ms682409(VS.85).aspx. The idea is to create a "job object" for your main application, and register your child processes with the job object. If the main process dies, the OS will take care of terminating the child processes.
For killing a child process after a given timeout, we can use the timeout command. It runs the command passed to it and kills it with the SIGTERM signal after the given timeout. In case we want to send a different signal like SIGINT to the process, we can use the –signal flag.
In chrome on Windows, the child processes are in a job object and so the OS takes care of killing them when the parent process dies.
Creating multiple process using fork() Explanation – Here, we had used fork() function to create four processes one Parent and three child processes. An existing process can create a new one by calling the fork( ) function. The new process created by fork() is called the child process.
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.:
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); } }
Then when each child process is created, execute the following code to launch each child each process and add it to the job object:
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 NOTE: See AssignProcessToJobObject always return "access denied" on Vista if you encounter access-denied issues with AssignProcessToObject() on vista.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With