Last active
November 30, 2022 13:54
-
-
Save jstimpfle/bd0bd81b1aaa900689cbd414f189d475 to your computer and use it in GitHub Desktop.
win32_proc_wait.cpp - Get notified when a Windows process terminates
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* win32_proc_wait.cpp - Get notified when a Windows process terminates */ | |
#include <Windows.h> | |
typedef void Proc_Terminated_Callback(void *data); | |
/* Proc_Wait - Waiting for a process to finish on Win32. | |
Zero out a Proc_Wait structure before use. | |
Call proc_wait_open() to register an asynchronous wait operation for a process handle. | |
The registration was successful iff "true" was returned. An unsuccessful registration has no effect | |
and you can attempt another registration later without having to zero out the struct. | |
A successfully registered wait operation must later be closed using proc_wait_close(). | |
It is ok (there will be no effect) if you call proc_wait_close() on a zeroed Proc_Wait | |
structure, or after a registration failed, or after the wait operation was already closed before. | |
If you close a process handle before closing the wait operation, behaviour is undefined. | |
*/ | |
struct Proc_Wait | |
{ | |
HANDLE hWait; | |
Proc_Terminated_Callback *callback; | |
void *data; | |
}; | |
void CALLBACK proc_wait_cb(PVOID data, BOOLEAN wastimer) | |
{ | |
assert(!wastimer); | |
Proc_Wait *pw = (Proc_Wait *) data; | |
pw->callback(pw->data); | |
} | |
bool proc_wait_open(Proc_Wait *pw, HANDLE hProc, Proc_Terminated_Callback callback, void *data) | |
{ | |
assert(!pw->hWait); | |
HANDLE hWait; | |
if (! RegisterWaitForSingleObject( | |
&hWait, | |
hProc, | |
&proc_wait_cb, | |
pw, | |
INFINITE, | |
WT_EXECUTEONLYONCE)) | |
{ | |
return false; | |
} | |
pw->hWait = hWait; | |
pw->callback = callback; | |
pw->data = data; | |
return true; | |
} | |
void proc_wait_close(Proc_Wait *pw) | |
{ | |
// Support calling this function multiple times, or on a zeroed Proc_Wait struct. | |
if (!pw->hWait) | |
return; | |
/* We're using UnregisterWaitEx() with INVALID_HANDLE_VALUE here to indicate | |
"no completion queue". Compared to this function, the normal | |
UnregisterWait() wouldn't be of good use for us: If the wait callback is | |
running while we're trying unregister it, then UnregisterWait() will return | |
immediately, without offering a wait to synchronize with the thread where | |
the callback is running - a race condition that would require us to add a | |
different means of synchronization. Instead, UnregisterWaitEx() will always | |
wait for the return of any callbacks that had already been started at the | |
time of the unregister request. */ | |
if (!UnregisterWaitEx(pw->hWait, INVALID_HANDLE_VALUE)) | |
assert(false); // this operation should never fail | |
pw->hWait = NULL; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment