RegisterWaitForSingleObject crash sometime if handle is closed immediately - c++

I'm getting a crash sometimes in RegisterWaitForSingleObject (1 out of 10). It seems that although RegisterWaitForSingleObject returns, the internal thread pool is not yet ready.
HANDLE processHandle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, processID);
// CRASH IN INTERNAL SOMETIMES
RegisterWaitForSingleObject (&hWaitForChild_,processHandle,OnChildProcessExit, 0,INFINITE,WT_EXECUTEONLYONCE);
// If I sleep here, then it seems ok.
//std::this_thread::sleep_for (std::chrono::milliseconds (10));
CloseHandle (processHandle);
I can replicate this with a simple sample here. 1 in 10 times, it will crash. How should I be synchronizing it properly without resorting to sleep hack.
https://filedn.com/l3TGy7Y83c247u0RDYa9fkp/temp/stackoverflow/testregister.cpp

based on your code spinet:
// THIS CRASHS HERE SOMETIMES
if (! RegisterWaitForSingleObject (
&hWaitForChild_
,processHandle
, OnChildProcessExit
, 0 //this
, INFINITE
, WT_EXECUTEONLYONCE))
{
LogDebug ("RegisterWaitForSingleObject failed");
}
// If this is enabled, then it won't crash
//std::this_thread::sleep_for (std::chrono::milliseconds (10));
if (! CloseHandle (processHandle)) // !!!
LogDebug ("RegisterWaitForSingleObject Closehandle failed");
so you close processHandle just after you call RegisterWaitForSingleObject for this handle. however if read about RegisterWaitForSingleObject:
If this handle is closed while the wait is still pending, the
function's behavior is undefined.
if look more deep - try understand - how is RegisterWaitForSingleObject worked internally ? it pass processHandle to some worker thread. and this thread begin wait for this handle. but this is (pass handle to another thread) is asynchronous operation - say for example internally can be started new thread with this handle as argument, or it can be passed to already existing working thread via some signal. but anyway - worked thread got this handle and begin wait some later. from another side - you just close processHandle after RegisterWaitForSingleObject return control. so here race - what will be first - or worked thread begin wait on handle (in this case all will be work) or you close this handle. in case you close this handle first - worked thread will be try wait on already invalid handle and raise exception - STATUS_THREADPOOL_HANDLE_EXCEPTION.
// If this is enabled, then it won't crash
//std::this_thread::sleep_for (std::chrono::milliseconds (10));
of course - by sleep you give time for worked thread to begin wait on handle. in this case he begin wait before you close handle.
solution - you must not close handle, until WAITORTIMERCALLBACK Callback will be not called. you need allocate some context, where place processHandle and pass this context to RegisterWaitForSingleObject. and when you callback will be called - you got pointer to your context back and here and close handle.
also note, that you not need open separate, second, handle for child process, but can use process handle returned by CreateProcess

Ok, I managed to solve it by keeping the handle around until I call Unregisterwait. It seems to be stable. Thanks to the answers.

I met the same problem like you that an exception occurred while debugging in Visual Studio. I tried many time and finally found the reason. If you close the handle of the process newly created, the program would crash. I tried to close the handles in the callback function, it works perfectly, like this:
typedef struct {
LPTSTR pszCmdLine;
HANDLE hEvent;
} THREAD_PARAM;
typedef struct {
TCHAR szCmdLine[1024];
HANDLE hWaitObject;
DWORD dwProcessId;
HANDLE hProcess;
DWORD dwThreadId;
HANDLE hThread;
} OBJECT_PARAM;
static void CALLBACK WaitObjectCallback(LPVOID lpParam, BOOLEAN TimerOrWaitFired)
{
OBJECT_PARAM *pobp = static_cast<OBJECT_PARAM *>(lpParam);
TCHAR szInfo[1024] = { 0 };
DWORD dwExitCode = 0;
GetExitCodeProcess(pobp->hProcess, &dwExitCode);
wnsprintf(szInfo, ARRAYSIZE(szInfo), _T("process %u [%s] exit: %u\n"), pobp->dwProcessId, pobp->szCmdLine, dwExitCode);
OutputDebugString(szInfo);
//
// unregister the wait object handle and close the process handle finally
//
UnregisterWait(pobp->hWaitObject);
CloseHandle(pobp->hProcess);
CloseHandle(pobp->hThread);
GlobalFree(lpParam);
}
static DWORD CALLBACK ThreadFunction(LPVOID lpParam)
{
THREAD_PARAM *pthp = static_cast<THREAD_PARAM *>(lpParam);
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi = { 0 };
BOOL bResult;
bResult = CreateProcess(nullptr, pthp->pszCmdLine, nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi);
if (bResult)
{
OBJECT_PARAM *pobp = static_cast<OBJECT_PARAM *>(GlobalAlloc(GPTR, sizeof(OBJECT_PARAM)));
// make copy of the command line and other informations of the newly created process
lstrcpyn(pobp->szCmdLine, pthp->pszCmdLine, ARRAYSIZE(pobp->szCmdLine));
pobp->dwProcessId = pi.dwProcessId;
pobp->hProcess = pi.hProcess;
pobp->dwThreadId = pi.dwThreadId;
pobp->hThread = pi.hThread;
bResult = RegisterWaitForSingleObject(&pobp->hWaitObject, pi.hProcess, WaitObjectCallback, pobp, INFINITE, WT_EXECUTEONLYONCE);
// once it failed...
if (!bResult)
{
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
}
// Notify the thread creator that the process is created successfully
SetEvent(pthp->hEvent);
return 0;
}

Related

Detecting a process crash in C++/Win32

I'm working on a software that contains 2 programs : the Qt Main exe + an OpenGL Game exe
We use always the Qt Main exe at the first. When we click on the button "start game", we execute the OpenGL Game exe. No probleme to do that.
The problem is that sometime we have a crash in the OpenGL Game exe and we want to send a crash report containing the log to our compagny crash-report mail.
I found a function (registerwaitforsingleobject) in Win32 API but I don't know if the process has crashed or not :
https://learn.microsoft.com/en-gb/windows/desktop/api/winbase/nf-winbase-registerwaitforsingleobject
I would like to use only the win32 api (WinXP-WinVist to Win10)
Thanks in advance
I found the solution to my problem : I used GetExitCodeProcess function from the Win32 API (https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess).
This is the example code :
int main(int argc, char** arv)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
const char * prgm = "CrashedProcess.exe";
LPSTR prgmLpstr = const_cast<LPSTR>(prgm);
// Start the child process.
if (!CreateProcess(NULL, // No module name (use command line)
prgmLpstr, // 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
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return -1;
}
// Wait until child process exits.
auto ret = WaitForSingleObject(pi.hProcess, INFINITE);
printf("WaitForSingleObject ret = %x\n", ret);
if (ret == WAIT_OBJECT_0)
{
printf("WaitForSingleObject ret ret == WAIT_OBJECT_0\n");
}
BOOL b = FALSE;
DWORD n = 0;
b = GetExitCodeProcess(pi.hProcess, &n);
if (n == 0xC0000005)
{
printf("Process Crashed !!!\n");
}
// Close process and thread handles.
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
printf("WaitForSingleObject end\n");
return 0;
}
CrashedProcess.exe source code :
int main()
{
int * ptr = nullptr;
*ptr = 123;
return 0;
}
Use a ready-made solution such as CrashRpt http://crashrpt.sourceforge.net/. It will install a proper handler and report/submit what you need when exceptions are thrown.
You can use Interprocess Communications with a pipe.
Send a message at time laps (for example, 1 second). If there's no response you can be almost sure that the other program is crashed.
Another approach, less elegant, is testing for a log file, modified every x-seconds, with a value meaning "I'm still alive, not crashed".
Assuming the program you care about has a normal Windows event loop, the more or less standard way to check that it's processing messages in a reasonably timely fashion is to use SendMessageTimeout to send it a WM_NULL message.
The program won't do anything in response to the WM_NULL, but SendMessageTimeout will time out if the message stays in its message queue for too long (where you pick what "too long" means when you make the call). So you send it, and then check whether it timed out or not.
But note: this only applies to programs that does process Windows messages. If it doesn't have a message loop, it'll always timeout. Oh, and a program is multi-threaded, one thread can "crash" (e.g., go into an infinite loop) while others continue to operate normally, so it's not always easy to even define what "crashed" means.

Call to WaitForSingleObject not clear in combination with CreateProcess

I came across the following code in a program that keeps track of processes:
void StartProcess(const std::wstring& processName, const CString& argument)
{
...
STARTUPINFO stInfo;
PROCESS_INFORMATION prInfo;
ZeroMemory( &stInfo, sizeof(stInfo) );
stInfo.cb = sizeof(stInfo);
stInfo.dwFlags=STARTF_USESHOWWINDOW;
stInfo.wShowWindow=SW_SHOWDEFAULT;
bRet = CreateProcess(NULL,
(LPTSTR)(LPCTSTR)sCmdline,
NULL,
NULL,
TRUE,
CREATE_NEW_CONSOLE | NORMAL_PRIORITY_CLASS,
NULL,
_T("."),
&stInfo,
&prInfo);
// Create process has gone OK and we have to wait.
if (bRet)
{
bRet = FALSE;
int nRetWait = WaitForSingleObject(prInfo.hProcess,0);
if (nRetWait == WAIT_OBJECT_0)
{
// Get the exit code of the process
DWORD dwExitCode = 0;
::GetExitCodeProcess(prInfo.hProcess, &dwExitCode);
if (0 == dwExitCode)
{
// The program succeeded
m_StartedServices.push_back(prInfo.dwProcessId;);
bRet = TRUE;
}
}
}
}
The code should start a process and then in a later stadium terminate it (using m_StartedServices). However I am wondering what added value the calls to WaitForSingleObject and GetExitCodeProcess have. I have looked around a bit and it seems that the WaitForSingleObject with a timeout of 0 is used to check if a process is still running, but it is just created, so why check? And why check the exit code of a process that is still running?
Can anybody clear this up?
Also I found that calls:
CloseHandle(prInfo.hThread);
CloseHandle(prInfo.hProcess);
are missing in this function. Have I found a handle leak, or is there some magic that would automatically close the handles?

Winapi Timer callback thread, never returns

I've got to debug some code which is not from me.
This code implement a timer API using winapi Timer interface.
I'm not very used to this Winapi functionality, so i could use your help :)
From what I understand this code is done like this :
=> Init()
timerQueue = CreateTimerQueue();
=> CreateTimer()
CreateTimerQueueTimer(timerHandle, timerQueue, timerCallback, ..., WT_EXECUTEDEFAULT);
=> timerCallback()
DeleteTimerQueueTimer(timerQueue , timerHandle, NULL));
calback() //Launch user-defined callback
=> CleanUp() // to be called at the end
DeleteTimerQueueEx(timerQueue , INVALID_HANDLE_VALUE);
When we test that, user-defined callback are executed successfully after the desired amount of time. But after that timerCallback threads keep pending and never return, preventing the all process to returns. Using VS debugger I can see those threads (named TppWorkerThread#4) on the thread...
Perhaps we miss something to make callback returns properly or we created some sort of deadlocks... However I cannot figure it out ...
Please let me know if I forgot some relevant information.
Thank you for your help.
EDIT:
Further information :
- Blocking thread are at this state at the end of the process :
* Category :Worker Thread
* Name : _TppWorkerThread#4
* Location : _ZwWaitForWorkViaWorkerFactory#8
* Priotity : Normal
EDIT2:
Having some more time to work on that strange behavior, I am now able to reproduce it in a standalone code.
#include <windows.h>
#include <stdio.h>
HANDLE gDoneEvent;
HANDLE hTimer[5];
HANDLE hTimerQueue = NULL;
HANDLE g_threadHandle;
void PeriodicCallback(void)
{
printf("Periodic routine called.\n");
}
void SingleCallback(void)
{
printf("Single routine called.\n");
if (!DeleteTimerQueueTimer(hTimerQueue, hTimer[2], NULL))
printf("DeleteTimerQueueTimer() fail. Return value is %d.\n", GetLastError());
}
void CALLBACK CommonCallback(PVOID lpParam, BOOLEAN TimerOrWaitFired)
{
printf("Common routine called. Parameter is %d.\n", *(int *)lpParam);
((void (*)(void))lpParam)();
}
void MainTest(void)
{
// Use an event object to track the TimerRoutine execution
gDoneEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (NULL == gDoneEvent)
{
printf("CreateEvent failed (%d)\n", GetLastError());
return -1;
}
if(0 == SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL))
{
printf("SetThreadPriority failed (%d)\n", GetLastError());
return -2;
}
// Create the timer queue.
hTimerQueue = CreateTimerQueue();
if (NULL == hTimerQueue)
{
printf("CreateTimerQueue failed (%d)\n", GetLastError());
return -3;
}
/*
if (!CreateTimerQueueTimer( &hTimer[2], hTimerQueue,
(WAITORTIMERCALLBACK)CommonCallback, &SingleCallback, 1000, 0, WT_EXECUTEDEFAULT))
{
printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
return -4;
}
*/
if (!CreateTimerQueueTimer( &hTimer[4], hTimerQueue,
(WAITORTIMERCALLBACK)CommonCallback, &PeriodicCallback, 10, 500, WT_EXECUTEDEFAULT))
{
printf("CreateTimerQueueTimer failed (%d)\n", GetLastError());
return -5;
}
// TODO: Do other useful work here
printf("Call timer routine in 10 seconds...\n");
Sleep(4000);
CloseHandle(gDoneEvent);
if (!DeleteTimerQueueTimer(hTimerQueue, hTimer[4], INVALID_HANDLE_VALUE))
printf("DeleteTimerQueueTimer failed (%d)\n", GetLastError());
// Delete all timers in the timer queue.
if (!DeleteTimerQueueEx(hTimerQueue, INVALID_HANDLE_VALUE))
printf("DeleteTimerQueue failed (%d)\n", GetLastError());
Sleep(1000);
ExitThread(0);
}
int main(int argc, char **argv[])
{
if(g_threadHandle == CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)MainTest, NULL, 0, NULL))
printf("Creation fail");
ExitThread(0);
}
I'm compiling this code on VisualStudio 2010 Professional.
It appears that event after calling DeleteTimerQueueTimer() some threads remain pending on the threads pool, preventing my process to shutdown. I still cannot figured it out ...
When you call DeleteTimerQueueEx with an INVALID_HANDLE_VALUE as its second parameter it will block until all callbacks which are running have completed. The Error may be in one of your callback functions which never returns.
You are calling DeleteTimerQueueTimer(timerQueue , timerHandle, NULL); with NULL as the third parameter, this will not wait for the callback to complete if one is running at the time you delete the timer. I suggest using DeleteTimerQueueTimer(timerQueue , timerHandle, INVALID_HANDLE_VALUE) which will block until the call back completes (if one is running). Calling cleanUp() without using the blocking version of DeleteTimerQueueTimer is likely a bug as you may be cleaning up at the same time as the callback is executing.
It could also be a problem of calling DeleteTimerQueueEx or DeleteTimerQueueTimer from within a callback, which is forbidden. Break on execution of DeleteTimerQueueEx and look at what thread you are in, if its a TppWorkerThread than you have found your bug.
EDIT:
In your comment you say you do call DeleteTimerQueueTimer from within the callback but don't use INVALID_HANDLE_VALUE, reading the documentation again from http://msdn.microsoft.com/en-us/library/windows/desktop/ms682569%28v=vs.85%29.aspx this does seem to be legal but I distinctly remember us making design decisions to avoid this, I'm sorry this is so vague, I hope someone can give authoritative advice on this.
We send an event/message to the queue of a non timer thread which then removes the timer, you could even have a dedicated thread for this but that is probably overkill. At the end of the day you need to be sure that the timer is removed before doing cleanup so you have to either block on removal or have some other thread do it upon signaling of an event.
After some work on that issue I think I got to an answer.
I appears that this timerQueue API is coded on top of threadPool winAPI, and when we ask to create a timerQueue Windows create a thread pool from where all callback will be launched.
Until here no problem, but, when we ask for timerQueue deletion, it appears that this thread pool is not deleted...
This result in some thread keeping pending waiting to be used and preventing the process to returns.
After some time (timeout??) those threads returns and the process exit.
I don't really get why this pool is not closed... but, now, I use a workaround :
exit(0);
At the end of my program, it's a bit brutal but it does the job (ie: killing my process, whatever threads are still pending or not)

Exit code of thread in Windows C++

Suppose I have created multiple threads.
Now I am waiting for multiple object as well using :
WaitOnMultipleObject(...);
Now if I want to know the status of all the thread's return code. How to do that ?
Do I need to loop for all the thread's handle in the loop.
GetExitCodeThread(
__in HANDLE hThread,
__out LPDWORD lpExitCode
);
And now check lpExitCode for success / failure code ?
Cheers,
Siddhartha
If you want to wait for a thread to exit, just wait on the thread's handle. Once the wait completes you can get the exit code for that thread.
DWORD result = WaitForSingleObject( hThread, INFINITE);
if (result == WAIT_OBJECT_0) {
// the thread handle is signaled - the thread has terminated
DWORD exitcode;
BOOL rc = GetExitCodeThread( hThread, &exitcode);
if (!rc) {
// handle error from GetExitCodeThread()...
}
}
else {
// the thread handle is not signaled - the thread is still alive
}
This example can be extended to waiting for completion of several thread by passing an array of thread handles to WaitForMultipleObjects(). Figure out which thread completed using the appropriate offset from WAIT_OBJECT_0 on the return from WaitForMultipleObjects(), and remove that thread handle from the handle array passed to WaitForMultipleObjects() when calling it to wait for the next thread completion.
Do I need to loop for all the thread's
handle in the loop.
GetExitCodeThread(
__in HANDLE hThread,
__out LPDWORD lpExitCode
);
Yes.

Safely synchronizing a COM thread

I've done a lot with multithreading in the past, but I'm fairly new to COM. Anyway, here's my issue:
I create a worker thread, which registers as an STA, and creates a COM object. Then the worker thread and the main thread try to communicate with each other. Using CoMarshalInterThreadInterfaceInStream and CoGetInterfaceAndReleaseStream, I can get the threads to call methods on the COM objects in the other thread.
Here's what the worker thread looks like:
void workerThread()
{
CoInitialize(NULL);
MyLib::IFooPtr foo = ...; // create my COM object
// Marshall it so the main thread can talk to it
HRESULT hr = CoMarshalInterThreadInterfaceInStream(foo.GetIID(),
foo.GetInterfacePtr(),
&m_stream);
if (FAILED(hr)) {
// handle failure
}
// begin message loop, to keep this STA alive
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1) break;
DispatchMessage(&msg);
}
}
In the main thread:
// launch the thread
m_worker = boost::thread (&workerThread);
// get the interface proxy
MyLib::IFooPtr foo;
LPVOID vp (NULL);
HRESULT hr = CoGetInterfaceAndReleaseStream(m_stream, foo.GetIID(), &vp);
if (SUCCEEDED(hr)) foo.Attach(static_cast<MyLib::IFoo*>(vp));
This creates the object (which takes a while to initialize), and allows the main thread to talk to it, and everything is properly synchronized with the COM Apartment stuff. As far as I can tell from reading msdn, this seems to be the right way to do things. Now the main thread can use its proxy to call methods on my COM object, and the worker thread will receive those calls over the message queue, properly dispatching them.
However, what about synchronizing these threads?
Obviously in this case I want the main thread to wait to call CoGetInterfaceAndReleaseStream until after the worker thread has created that stream via CoMarshalInterThreadInterfaceInStream. But how can I safely do that?
From MSDN, I should be using something like MsgWaitForMultipleObjects, so I can wait for my_condition OR new_message_arrived, and then I can do something like:
// verbatim from msdn
while (TRUE)
{
// wait for the event and for messages
DWORD dwReturn = ::MsgWaitForMultipleObjects(1,
&m_hDoneLoading, FALSE, INFINITE, QS_ALLINPUT);
// this thread has been reawakened. Determine why
// and handle appropriately.
if (dwReturn == WAIT_OBJECT_0)
// our event happened.
break ;
else if (dwReturn == WAIT_OBJECT_0 + 1)
{
// handle windows messages to maintain
// client liveness
MSG msg ;
while(::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
::DispatchMessage(&msg) ;
}
}
But how do I mix boost::thread.join() and boost::condition.wait() with MsgWaitForMultipleObjects? Is that even possible, or do I have to do something else to avoid a race condition?
Your main thread has a message queue (must be, since is an STA host), why not simply post a message to it, PostThreadMessage? Post an user message (WM_USER +X) and your normal main thread message pump can handle this user message as a notification that the COM object has marshaled the interface into the stream and the main thread is safe to call CoGetInterfaceAndReleaseStream.
I must call out though that with your current design your worker thread does basically nothing more than just run an additional message pump. Any call to any method on your interface from the main thread will block, wait for the worker thread to pick up the message from its message queue, process the call, respond, and then the main thread will resume. All operations will be at least as slow as having the COM object hosted in the main thread, plus the overhead of COM marshaling back and forth between the two STAs. Basically there is no concurrency whatsoever between the two threads, because of how COM STA works. Are you sure is this what you want?
Edit
(omitting a bunch of details like number of threads, timeout handling, assignment of a stream/IID/CLSID for each worker etc etc)
in the .h:
HANDLE m_startupDone;
volatile int m_threadStartCount;
worker thread:
void workerThread()
{
CoInitialize(NULL);
MyLib::IFooPtr foo = ...; // create my COM object
// Marshall it so the main thread can talk to it
HRESULT hr = CoMarshalInterThreadInterfaceInStream(foo.GetIID(),
foo.GetInterfacePtr(),
&m_stream);
if (FAILED(hr)) {
// handle failure
// remember to decrement and signal *even on failure*
}
if (0 == InterlockedDecrement(&m_threadStartCount))
{
SetEvent (m_startupDone);
}
// begin message loop, to keep this STA alive
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1) break;
DispatchMessage(&msg);
}
}
in the main thread:
m_startupDone = CreateEvent (NULL, FALSE, FALSE, NULL);
m_threadStartCount = <number of workerthreads>
// launch the thread(s)
m_worker = boost::thread (&workerThread);
m_worker2 = boost::thread (&workerThread);
...
// now wait for tall the threads to create the COM object(s)
if (WAIT_OBJECT0 != WaitForSingleObject(m_startupDone, ...))
{
// handle failure like timeout
}
// By now all COM objects are guaranteed created and marshaled, unmarshall them all in main
// here must check if all threads actually succeeded (could be as simple as m_stream is not NULL)
// get the interface proxy
MyLib::IFooPtr foo;
LPVOID vp (NULL);
HRESULT hr = CoGetInterfaceAndReleaseStream(m_stream, foo.GetIID(), &vp);
if (SUCCEEDED(hr)) foo.Attach(static_cast<MyLib::IFoo*>(vp));