Process Termination waiting for Event - Win32
-
I have a Win32 Service (written in C) that does a CreateProcess(). After that it waits for its own termination (the services'). I would like to monitor the subprocess such that the service gets notified when the subprocess terminates (for whatever reason). I have an idea of doing this with events and WaitForMultipleObjects(), but somehow I'm missing the idea where to start. Should the service create an event? Or should the subprocess do that? And how would that be notified to the service process so that it can wait for that event? Help very much appreciated. -- Christoph
-
I have a Win32 Service (written in C) that does a CreateProcess(). After that it waits for its own termination (the services'). I would like to monitor the subprocess such that the service gets notified when the subprocess terminates (for whatever reason). I have an idea of doing this with events and WaitForMultipleObjects(), but somehow I'm missing the idea where to start. Should the service create an event? Or should the subprocess do that? And how would that be notified to the service process so that it can wait for that event? Help very much appreciated. -- Christoph
If I understand you right, you start some processes within your service and then you wanna wait till the processes ends? If so, then I would use the handle hProcess from the PROCESS_INFORMATION you get by calling CreateProcess and then use WaitForSingleObject or WaitForMultipleObjects.
Greetings Covean
-
If I understand you right, you start some processes within your service and then you wanna wait till the processes ends? If so, then I would use the handle hProcess from the PROCESS_INFORMATION you get by calling CreateProcess and then use WaitForSingleObject or WaitForMultipleObjects.
Greetings Covean
Thanks for answering. I thought so as well. Could you supply some sample code? Does the -->>> WaitForSingleObject(pi.hProcess,INFINITE); hang in that function call? Then I would not reach the code section after it which already contains : I think I have to create some sort of event and put it in the hEvents[] array.
// Start the child process. if( !CreateProcess( NULL, // No module name (use command line). execpath, // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. 0, // No creation flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi ) // Pointer to PROCESS\_INFORMATION structure. ) // Wait until child process exits. //--->>>> WaitForSingleObject( pi.hProcess, INFINITE ); while(1) { dWait=WaitForMultipleObjects(1,hEvents,FALSE,0); if(dWait == WAIT\_OBJECT\_0) break; Sleep(1000);/\* millisec \*/ } cleanup: if(pi.hProcess){ //GetExitCodeProcess ( pi.hProcess, &procstat ); TerminateProcess(pi.hProcess,-1); //terminated by service termination fprintf(logfile,"Subprocess %s terminated by service\\n", execpath );
-- Christoph
modified on Wednesday, November 11, 2009 8:42 AM
-
Thanks for answering. I thought so as well. Could you supply some sample code? Does the -->>> WaitForSingleObject(pi.hProcess,INFINITE); hang in that function call? Then I would not reach the code section after it which already contains : I think I have to create some sort of event and put it in the hEvents[] array.
// Start the child process. if( !CreateProcess( NULL, // No module name (use command line). execpath, // Command line. NULL, // Process handle not inheritable. NULL, // Thread handle not inheritable. FALSE, // Set handle inheritance to FALSE. 0, // No creation flags. NULL, // Use parent's environment block. NULL, // Use parent's starting directory. &si, // Pointer to STARTUPINFO structure. &pi ) // Pointer to PROCESS\_INFORMATION structure. ) // Wait until child process exits. //--->>>> WaitForSingleObject( pi.hProcess, INFINITE ); while(1) { dWait=WaitForMultipleObjects(1,hEvents,FALSE,0); if(dWait == WAIT\_OBJECT\_0) break; Sleep(1000);/\* millisec \*/ } cleanup: if(pi.hProcess){ //GetExitCodeProcess ( pi.hProcess, &procstat ); TerminateProcess(pi.hProcess,-1); //terminated by service termination fprintf(logfile,"Subprocess %s terminated by service\\n", execpath );
-- Christoph
modified on Wednesday, November 11, 2009 8:42 AM
A process handle acts as a kind of "event" and its fired if the process terminates, so you can add this handle to your hEvents array.
Does the -->>> WaitForSingleObject(pi.hProcess,INFINITE) hang in that function call?
Yes if you use INFINITE as time interval. :laugh: Here some code for you:
HANDLE hObjectsToWaitFor[2];
hObjectsToWaitFor[0] = hSomeEventHandle;
hObjectsToWaitFor[1] = pi.hProcess;while(1)
{
dWait = WaitForMultipleObjects(2, &hObjectsToWaitFor, FALSE, 1000 /*do not use sleep cause this function can do this for you*/);
switch(dWait)
{
case WAIT_OBJECT_0 + 0: /*hSomeEventHandle fired*/
{
// do something
break;
}
case WAIT_OBJECT_0 + 1: /*pi.hProcess fired*/
{
// the started process has terminated
GetExitCodeProcess ( pi.hProcess, &procstat );
// do something
break;
}
default: // Timeout
{
// do something
break;
}
}
}[edit] read the remarks section of WaitForMultipleObjects to see what kind of handles you also can wait for with. (Examples: Event, Memory resource notification, Mutex, Process, Semaphore, Thread)
Greetings Covean
-
A process handle acts as a kind of "event" and its fired if the process terminates, so you can add this handle to your hEvents array.
Does the -->>> WaitForSingleObject(pi.hProcess,INFINITE) hang in that function call?
Yes if you use INFINITE as time interval. :laugh: Here some code for you:
HANDLE hObjectsToWaitFor[2];
hObjectsToWaitFor[0] = hSomeEventHandle;
hObjectsToWaitFor[1] = pi.hProcess;while(1)
{
dWait = WaitForMultipleObjects(2, &hObjectsToWaitFor, FALSE, 1000 /*do not use sleep cause this function can do this for you*/);
switch(dWait)
{
case WAIT_OBJECT_0 + 0: /*hSomeEventHandle fired*/
{
// do something
break;
}
case WAIT_OBJECT_0 + 1: /*pi.hProcess fired*/
{
// the started process has terminated
GetExitCodeProcess ( pi.hProcess, &procstat );
// do something
break;
}
default: // Timeout
{
// do something
break;
}
}
}[edit] read the remarks section of WaitForMultipleObjects to see what kind of handles you also can wait for with. (Examples: Event, Memory resource notification, Mutex, Process, Semaphore, Thread)
Greetings Covean
Great! Many thanks. Just a minor drawback: When I stay in the while loop and the pi.hProcess has fired, the event sustains. Is there a way to reset the event automatically (or programmatically)? -- Christoph [edit] I did the following (not sure whether it's correct):
while(1) {
dWait = WaitForMultipleObjects(2, &hEvents\[0\], FALSE, 1000 /\* ersetzt Sleep() \*/); switch(dWait) { case WAIT\_OBJECT\_0 + 0: /\* hServerStopEvent gefeuert\*/ { goto cleanup; break; } case WAIT\_OBJECT\_0 + 1: /\* pi.hProcess gefeuert \*/ { // the started process has terminated timestamp(),fprintf(logfile,"Subprozess hat beendet mit exitcode %d, was tun?\\n", GetExitCodeProcess ( pi.hProcess, &procstat ));fflush(logfile); **ResetEvent(hEvents\[1\]); hEvents\[1\]=NULL;** // do something break; } default: // Timeout { // do something break; } } }
modified on Wednesday, November 11, 2009 10:01 AM
-
Great! Many thanks. Just a minor drawback: When I stay in the while loop and the pi.hProcess has fired, the event sustains. Is there a way to reset the event automatically (or programmatically)? -- Christoph [edit] I did the following (not sure whether it's correct):
while(1) {
dWait = WaitForMultipleObjects(2, &hEvents\[0\], FALSE, 1000 /\* ersetzt Sleep() \*/); switch(dWait) { case WAIT\_OBJECT\_0 + 0: /\* hServerStopEvent gefeuert\*/ { goto cleanup; break; } case WAIT\_OBJECT\_0 + 1: /\* pi.hProcess gefeuert \*/ { // the started process has terminated timestamp(),fprintf(logfile,"Subprozess hat beendet mit exitcode %d, was tun?\\n", GetExitCodeProcess ( pi.hProcess, &procstat ));fflush(logfile); **ResetEvent(hEvents\[1\]); hEvents\[1\]=NULL;** // do something break; } default: // Timeout { // do something break; } } }
modified on Wednesday, November 11, 2009 10:01 AM
You can try ResetEvent or change this event handle to an "empty" event you only create but never fire, but I think the best way is to recreate the handle array without the process handle (be aware of that also the WAIT_OBJECT_0 + x value for all other events (after the process handle) changes if you remove this handle). Here some pseudocode how I would solve this problem.
#define TIMEOUT_EVENT 0
struct WaitObject
{
HANDLE hWaitFor;
int nEventId;
}int WaitForObjects(WaitObject[] waitObjects, bool bWaitAny, ....)
{
int nRetVal = 0;
int nLoop = 0;
HANDLE arrayWaitObjectHandles[waitObjects.Length]; // ok its not really C ^^
for(; nLoop < waitObjects.Length; nLoop++)
arrayWaitObjectHandles[nLoop] = waitObjects[nLoop].hWaitFor;nRetVal = WaitForMultipleObjects(waitObjects.Length, &arrayWaitObjectHandles, ...); if(nRetVal == TIMEOUT) return TIMEOUT\_EVENT; return waitObjects\[nRetVal - WAIT\_OBJECT\_0\].nEventId;
}
I know that this is not fully C (its too long ago^^) but I hope you understand the idea behind this, just to build a function that waits for you and returns event ids (you assigned), so it will be easier to remove the process handle from this array, because you waits for your assigned event ids. I hope that helps. PS: Viel Spass damit! ;P
Greetings Covean