Detecting a process crash in C++/Win32 - c++

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.

Related

RegisterWaitForSingleObject crash sometime if handle is closed immediately

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;
}

CMD Exception Handling C/C++

I will use some CMD commands in my program and these commands might throw some exceptions. And as you know, when an exception accours, CMD writes its own error message the screen. But, I want to write my own error message.
My question is this: Is there a way to block CMD messages and write only my own error messages?
P.S. This is not a complex program. It executes CMD commands using System().
Example:
Let's say, the user can rename and copy any files in the program. As you know, if the user does not enter file's path properly, an error message is showed on the screen. And I want that this error message never appears on the screen. Only my own error message is showed.
Thank you!
It depends on your platform and the commands you are going to use. The usage of system() for calling console commands is by the way strongly discouraged by most people (it's way to heavy for most purposes).
I would suggest to you using CreateProcess() with the CREATE_NO_WINDOW flag and waiting for the process to exit with a call to WaitForSingleObject() and GetExitCodeProcess().
This approach utilizes the fact, that most CMD command are executables, located somewhere in C:/Windows/....
/*
* Executes a program and returns it's exit code.
*
* TODO: Error checking should be added for
* CreateProcess()
* WaitForSingleObject()
* GetExitCodeProcess()
*/
DWORD ExecCmdLine(TCHAR const* cmdline)
{
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
::CreateProcess(NULL, cmdline, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
::CloseHandle(pi.Thread);
::WaitForSingleObject(pi.hProcess, INFINITE);
DWORD exitcode;
::GetExitCodeProcess(pi.hProcess, &exitcode);
::CloseHandle(pi.hProcess);
return exitcode;
}
If you want to retrieve the output of the command you could also provide hStdOutput, hStdError in the STARTUPINFO structure and set STARTF_USESTDHANDLES in STARTUPINFO.dwFlags.
You can even do other things in your own program while the command is executing (especially as you mentioned file copy). This one is done the C++ way:
/*
* TODO: Error checking should be added for
* CreateProcess()
* WaitForSingleObject()
* GetExitCodeProcess()
*/
class AsyncCmd
{
public:
AsyncCmd(std::string const& cmdline)
: cmdline(cmdline),
processHandle(NULL)
{
}
~AsyncCmd()
{
if (this->processHandle != NULL)
::CloseHandle(this->processHandle);
}
// Starts the execution of the commandline.
void Start(HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE), HANDLE hErr = GetStdHandle(STD_ERROR_HANDLE))
{
STARTUPINFO si;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = hOut;
si.hStdError = hErr;
PROCESS_INFORMATION pi;
memset(&pi, 0, sizeof(pi));
::CreateProcess(NULL, this->cmdline.c_str(), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
::CloseHandle(pi.hThread);
this->processHandle = pi.hProcess;
}
// Blocks until execution is finished and returns the exit code.
DWORD ExitCode()
{
::WaitForSingleObject(this->processHandle, INFINITE);
DWORD exitcode;
::GetExitCodeProcess(this->processHandle, &exitcode);
return exitcode;
}
private:
AsyncCmd(AsyncCmd const&);
AsyncCmd& operator=(AsyncCmd const&);
std::string cmdline;
HANDLE processHandle;
}
To rephrase what's already been said:
Q: Can you somehow intercept an error thrown by a command you've invoked via "system()"?
A: No. For many reasons.
But you can redirect the textual error message that's written by the command line program:
Redirecting "stderr" is relatively easy. "GetStdHandle(STD_ERROR_HANDLE)" is one way. Redirecting to "> :err" is another.
Unfortunately, not all programs are nice enough to write error messages to "stderr".
Many write everything to "stdout".
In the latter case, you'd have to figure out 1) that an error actually occurred, and 2) figure out how to separate the parts of the text input that are "standard output", vs those parts that are "error text".
PS:
An alternative API to "system()" is "popen()".
One brute force way to do it would be to pipe the output of the CMD i.e. yourCommand > file.txt to a file and then read the file contents to determine if there was an exception.
Adding to what yourmt wrote, I'd like to point out that exceptions won't bleed through across process boundaries. So what you are tackling here is the output (both stderr and stdout) of the executed program (and shell) plus its exit code (in case this provides any useful information). This is mostly so you understand that this is literally not about exception handling as your title implies.
That means you can set hStdOutput and hStdError when using CreateProcess/CreateProcessEx to use pipes that you control and where you "catch" the output and then replace it with your own before outputting it to the console. In case you want to only replace stderr you can also do that.
You can use
#include "Exception.h"
class MyClass
{
public:
class Error : public Exception { };
MyClass();
~MyClass();
void myFunction() throw(Error);
}
...
catch (MyClass::Error & error)
{
cout << error.full_message << endl;
return;
}
and
class Exception
{
public:
std::string message;
std::string full_message;
virtual char * info() { return ""; };
void setMessage(std::string msg)
{
message = msg;
if (*info() == 0) { full_message = msg; }
else { full_message = MakeString() << info() << " " << msg; }
}
};
// template function ///////////////////////////////////////////
template <class errType>
void Throw(const std::string msg=std::string(""))
{
errType err;
err.setMessage(msg);
throw(err);
}

Launching an application from a thread with C++

I need to launch a 3rd party program inside a thread, wait to get the results both from stdout/stderr with C++.
What methods are available?
Are they cross-platform? I mean, can I use them both for cl/gcc?
On Unix:
http://linux.die.net/man/3/execl
#include <sys/types.h>
#include <unistd.h>
void run_process (const char* path){
pid_t child_pid;
/* Duplicate this process. */
child_pid = fork ();
if (child_pid != 0){
/* This is the parent process. */
int ret = waitpid(child_pid, NULL, 0);
if (ret == -1){
printf ("an error occurred in waitpid\n");
abort ();
}
}
else {
execl (path, path);
/* The execvp function returns only if an error occurs. */
printf ("an error occurred in execl\n");
abort ();
}
}
On Windows:
http://msdn.microsoft.com/en-us/library/ms682425%28v=vs.85%29.aspx
# include <windows.h>
void run_process (const char* path){
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
bool ret = = CreateProcess(
NULL, // No module name (use command line)
path, // 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
)
if (!ret){
printf("Error");
abort();
}
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
system should be platform independant, but you might want to stick with createprocess (win)/ exec (others) if there is a concern about running the program with the same security privledges.
There is a set of posix functions to launch an external executable - see exec - which are cross platform. To do some specific tasks on windows you may need to use windows specific createprocess.
These generally block so you would have to start them in a new thread. Threading is generally not cross platform, although you can use posix (pthreads) on windows.
An alternative is to use somthing like Qt or wxWidgets cross platform libraries.

Overlapped ReadFileEx on Child Process' Redirected STDOUT Never Fires

I have a long-running console-based application Sender that sends simple text to STDOUT using non-buffered output such as cout << "Message" << flush(). I want to create an MFC dialog-based application (named Receiver) that starts Sender and can read it's output. Receiver should also be able to detect when Sender has died, or be able to kill Sender if it wants to. Sender knows nothing of Reciever, and I can't change Sender's code.
I have asked a separate question about the best way to do this. My first attempt was to create pipes with redirected STDIN and STDOUT for the child process and use asynchronous ReadFileEx calls to read in Sender's data. This isn't working correctly, because the ReadFileEx function only fires once, and only with zero bytes transferred even though I know for a fact that Sender is sending data.
I am creating 2 pipes with redirected STDIN and STDOUT, ala this MS example:
// allow the child process to inherit handles
SECURITY_ATTRIBUTES sa = {0};
sa.nLength = sizeof(sa);
sa.bInheritHandle = 1;
// create pipes with rerouted stdin & stdout
CreatePipe(&handles[h_Child_StdOut_Read], &handles[h_Child_StdOut_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdOut_Read], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&handles[h_Child_StdIn_Read], &handles[h_Child_StdIn_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdIn_Read], HANDLE_FLAG_INHERIT, 0);
...Receiver then goes on to start Sender via CreateProcess():
// create child process
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(si);
si.hStdOutput = handles[h_Child_StdOut_Write];
si.hStdInput = handles[h_Child_StdIn_Read];
si.dwFlags |= STARTF_USESTDHANDLES;
CreateProcess( 0, "Sender.EXE", 0, 0, 1, 0, 0, 0, &si, &pi);
handles[h_Child_Process] = pi.hProcess;
handles[h_Child_Thread] = pi.hThread;
My main loop is based on WaitForObjectsEx, placed in to an alertable wait state to support the asynch file read. I am waiting on two handles: one that signals when Sender dies prematurely, and one that signals when Receiver's main thread wants Sender to die. Before starting the loop, I kick off an overlapped (asynchronous) file read operation on Sender's STDOUT. Ignore the obvious memory leaks and other hacks -- this is illustrative:
vector<HANDLE> wait_handles;
wait_handles.push_back(handles[h_Die_Sig]);
wait_handles.push_back(handles[h_Child_Process]);
for( bool cont = true; cont; )
{
IO* io = new IO;
memset(io, 0, sizeof(IO));
io->buf_size_ = 16 * 1024;
io->buf_ = new char[io->buf_size_];
memset(io->buf_, 0, io->buf_size_);
io->thread_ = &param;
io->file_ = handles[h_Child_StdOut_Read];
if( !ReadFileEx(io->file_, io->buf_, io->buf_size_, io, OnFileRead) )
{
DWORD err = GetLastError();
string err_msg = util::strprintwinerr(err);
}
DWORD rc = WaitForMultipleObjectsEx(wait_handles.size(), &wait_handles[0], FALSE, INFINITE, TRUE);
// ...
}
The IO object above is derived publicly from OVERLAPPED:
struct IO : public OVERLAPPED
{
char* buf_;
DWORD buf_size_;
DWORD read_;
ThreadParam* thread_;
HANDLE file_;
};
When the overlapped Read function completes, I read the incoming data and generate a string:
void CALLBACK OnFileRead(DWORD err, DWORD bytes, OVERLAPPED* ovr)
{
IO* io = static_cast<IO*>(ovr);
string msg(io->buf_, bytes);
}
Sender knows nothing of Receiver, and it sends text to the console using very simple, but non-buffered means.
The problem: I know that Sender is sending data to its STDOUT, but my OnFileRead function is called only once, and only with zero bytes transferred.
Why can't I receive Sender's output this way? Do I have a bug, or am I doing something wrong?
Besides the error pointed out by #DyP, you are assuming that CreatePipe opened the handle in overlapped mode. Your assumption is incorrect. Microsoft documents it:
Asynchronous (overlapped) read and write operations are not supported
by anonymous pipes. This means that you cannot use the ReadFileEx and
WriteFileEx functions with anonymous pipes. In addition, the
lpOverlapped parameter of ReadFile and WriteFile is ignored when these
functions are used with anonymous pipes.
(Indeed, if you look inside kernel32.dll, on Windows XP for example, CreatePipe does not set the lower bit on the seventh parameter to NtCreateNamedPipeFile; that bit is set when CreateNamedPipe is called with FILE_FLAG_OVERLAPPED.)
Look for Dave Hart's MyCreatePipeEx implementation; it can be used as a drop-in replacement for CreatePipe when overlapped I/O is needed. Simply change PipeSerialNumber++ to InterlockedIncrement(&PipeSerialNumber) to avoid race conditions in MT code.
I think you have a typo:
CreatePipe(&handles[h_Child_StdOut_Read], &handles[h_Child_StdOut_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdOut_Read], HANDLE_FLAG_INHERIT, 0);
CreatePipe(&handles[h_Child_StdIn_Read], &handles[h_Child_StdIn_Write], &sa, 0);
SetHandleInformation(handles[h_Child_StdIn_Read], HANDLE_FLAG_INHERIT, 0);
change the last one to
SetHandleInformation(handles[h_Child_StdIn_Write], HANDLE_FLAG_INHERIT, 0);
that's also what they do at the MSDN example.

Launching external application and block current application till the launched application quit

I am not sure whether there is a way to
Launch an external application, and block current application till the launched application had quit.
Currently, I am using the following non-blocking method (MFC) to launch
std::string str = "Notepad2.exe";
// Non-blocking. Return immediately.
WinExec(str.c_str(), SW_SHOW);
code:
SHELLEXECUTEINFO sei = {0};
sei.cbSize = sizeof (SHELLEXECUTEINFO);
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
sei.lpVerb = "open";
sei.lpFile = "notepad.exe";
sei.nShow = SW_SHOWNORMAL;
if (ShellExecuteEx (&sei))
{
WaitForSingleObject (sei.hProcess, INFINITE);
}
As Jerry points out, this is bad for your own GUI. But if the process you launch, directly or indirectly, does a broadcast SendMessage then this can cause catastrophic deadlock, because your process has a window but isn't pumping any messages: the launched process is waiting for your code to handle its message, and you're waiting for it. Clang...
You could use MsgWaitForMultipleObjects instead, or better still, split the launch-and-wait off into a thread and simply disable any part of your UI you don't want the user to interact with.
ShellExecuteEx with SEE_MASK_NOCLOSEPROCESS will (among other things) give you a handle to the new process. You can do a WaitForSingleObject on that handle, which will be signaled when it terminates. BTW, for a GUI program, this is almost always a bad idea -- making your GUI unresponsive until another program exits is really a poor idea.
If you just want to launch a process, you don't have to use ShellExecuteEx, use CreateProcess instead. Here is an untested example:
std::wstring commandLine = L"Notepad2.exe"
std::wstring::size_type length = commandLine.size();
boost::scoped_array<WCHAR> buffer(new WCHAR[length + 1]);
std::copy(commandLine.begin(), commandLine.end(), buffer.get());
buffer[length] = L'\0';
STARTUPINFO startupInfo;
ZeroMemory(&startupInfo, sizeof startupInfo);
startupInfo.cb = sizeof startupInfo;
PROCESS_INFORMATION processInfo;
CreateProcess(NULL, buffer.get(), NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo);
CloseHandle(processInfo.hThread);
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);