Could anyone kindly tell me how to kill child processes when the calling (parent) process is forcefully terminated? By the way, I am not able to change the source code of child application.
I have checked the existing thread in StackOverflow and it seems JobObject is the correct way to do so. However when I tested it (using a console application to call notepad.exe), I found that when the console application exited, Notepad didn't.
I used CreateProcess
to spawn the new process.
I have also seen somebody says that setting up a pipe between parent process and child process will do the job, but I have not yet tried it.
If anyone can give me some hints, I would really appreciate it.
Update: WINAPI AssignProcessToJobObject
failed to work if without | CREATE_BREAKAWAY_FROM_JOB
in CreatProcess
. Now it works!
Thank everyone.
Update again:
It's really tricky. I am always confused by Windows API.
Group 1:
Process flag: CREATE_SUSPENDED
JobObject flag: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_SECURITY_RESTRICTED_TOKEN or JOB_OBJECT_SECURITY_NO_ADMIN or JOB_OBJECT_LIMIT_BREAKAWAY_OK
Result: AssingProcessToJobObject
fails with Error code 5 Access is denied
Group 2:
Process flag: CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB
JobObject flag: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_SECURITY_RESTRICTED_TOKEN or JOB_OBJECT_SECURITY_NO_ADMIN
Results: AssingProcessToJobObject
succeeds, but child process fails to be killed when parent one is killed.
Group 3:
Process flag: CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB
JobObject flag: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
Results: AssingProcessToJobObject
succeeds, and child process is automatically killed when parent one is killed.
Group 4:
Process flag: CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB
JobObject flag: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK
Results: same to Group 3.
The following code uses JobObeject which I copied from http://cboard.cprogramming.com/windows-programming/60561-program-termination.html#post430075
#define _WIN32_WINNT 0x0500
#include <windows.h>
int main(void)
{
HANDLE hJob;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
/*
* Create a job object.
*/
hJob = CreateJobObject(NULL, NULL);
/*
* Causes all processes associated with the job to terminate when the
* last handle to the job is closed.
*/
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(hJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));
/*
* Create the process suspended.
*/
si.cb = sizeof(si);
CreateProcess(TEXT("C:\\Windows\\System32\\Notepad.exe"), NULL, NULL, NULL, FALSE,
CREATE_SUSPENDED | CREATE_BREAKAWAY_FROM_JOB /*Important*/, NULL, NULL, &si, &pi);
/*
* Add the process to our job object.
*/
AssignProcessToJobObject(hJob, pi.hProcess); // Does not work if without CREATE_BREAKAWAY_FROM_JOB
/*
* Start our suspended process.
*/
ResumeThread(pi.hThread);
/*
* At this point, if we are closed, windows will automatically clean up
* by closing any handles we have open. When the handle to the job object
* is closed, any processes belonging to the job will be terminated.
* Note: Grandchild processes automatically become part of the job and
* will also be terminated. This behaviour can be avoided by using the
* JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK limit flag.
*/
/*
* Do what you like here. For demonstration purposes we will just wait
* for the child process to complete. Click our close button to see
* everything in action.
*/
WaitForSingleObject(pi.hProcess, 3000);
/*
* Cleanup. As mentioned, Windows does this automagically when our process
* exits, but it is good style to do it explicitly.
*/
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(hJob);
return 0;
}
Do NOT test from within Visual Studio, via F5 or Ctrl+F5. When Visual Studio launch your program, it itself uses Job to manage things, and that interacts badly with your code.
Open a console and launch your exe "manually". Your code is correct ("works here", with VS2010 on Seven)
Edit: you may add error checking, don't assume all APIs always succeed.
Edit: you may use the IsProcessInJob API to know whether your process is already in a job when starting. If this is the case, child processes, by default, are created in that preexisting job, and you then have to use CREATE_BREAKAWAY_FROM_JOB
(if you don't, you can't use AssignProcessToJobObject
)
When starting the process from Visual Studio, or by double click in the Explorer,the process is launched in a job.
Adding, my code based on yours, works from VS or Explorer.
#include <Windows.h>
#include <stdio.h>
int main( void ) {
BOOL bIsProcessInJob;
BOOL bSuccess = IsProcessInJob( GetCurrentProcess(), NULL, &bIsProcessInJob );
if ( bSuccess == 0 ) {
printf( "IsProcessInJob failed: error %d\n", GetLastError() );
return 0;
}
if ( bIsProcessInJob ) {
MessageBox( NULL, L"Process is already in Job", L"Job Test", 0 );
}
HANDLE hJob = CreateJobObject( NULL, NULL );
if ( hJob == NULL ) {
printf( "CreateJobObject failed: error %d\n", GetLastError() );
return 0;
}
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
bSuccess = SetInformationJobObject( hJob, JobObjectExtendedLimitInformation, &jeli, sizeof( jeli ) );
if ( bSuccess == 0 ) {
printf( "SetInformationJobObject failed: error %d\n", GetLastError() );
return 0;
}
PROCESS_INFORMATION pi = { 0 };
STARTUPINFO si = { 0 };
si.cb = sizeof( si );
DWORD dwCreationFlags = bIsProcessInJob ? CREATE_BREAKAWAY_FROM_JOB : 0;
bSuccess = CreateProcess( L"C:\\Windows\\System32\\Notepad.exe", NULL, NULL, NULL, FALSE,
dwCreationFlags, NULL, NULL, &si, &pi);
if ( bSuccess == 0 ) {
printf( "CreateProcess failed: error %d\n", GetLastError() );
return 0;
}
bSuccess = AssignProcessToJobObject( hJob, pi.hProcess );
if ( bSuccess == 0 ) {
printf( "AssignProcessToJobObject failed: error %d\n", GetLastError() );
return 0;
}
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
printf( "Type a key to exit..." );
getchar();
CloseHandle( hJob );
return 0;
}
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