C++ - Windows - catch process exit from Task Manager - c++

I need to stop a service when our program has been killed with the task manager.
I tried with std::signal(...) and _onexit(...) but it does not work.
I tried running ProcessMonitor so check a sort of signal I can catch, but I did not find one.
I tried with a:
auto serviceStopThread = QThread::create([](){
::WaitForSingleObject(::GetCurrentProcess(), INFINITE);
ServiceUtils::stopService();
});
serviceStopThread->start();
but it does nothing.
How can I do?

While the process is still alive, find the PID, and open it with OpenProcess. You’ll need at least SYNCHRONIZE permission.
Then wait for the handle to become signaled. For example, you can launch a new thread, and call WaitForSingleObject with INFINITE timeout. The handle becomes signaled as soon as the process quits, regardless on the reason.
React however you like but don’t forget to call CloseHandle when you’re done.
If you only want to react when the process is killed suddenly, send some message to your supervising process when the program exits gracefully, to disable the handling.

Related

How to detect if my Windows application has ended?

Basically what the title says I need to detect when my program is ending like when someones clicks on end task in the task manager or something. Can anyone point me to some kind of event that handles this with an example or something? Thanks for any help given
You need to open this process. This way you will retrieve its handle. After that you can simply wait on this handle.
HANDLE h = OpenProcess(....);
WaitForSingleObject(h);
Handles of the processes and threads in many ways look like Windows event handles. Once this process or thread finishes, they get signaled.
It depends on how your app is terminated and what type of app it is.
For apps with an UI:
If the user clicks "End Task" in the task manager, you will actually receive WM_DESTROY and even WM_CLOSE messages to your message handler.
If the user simply clicks the X button of your app, obviously the above also applies.
If the user logs off or shuts down the PC, you'll receive WM_QUERYENDSESSION and WM_ENDSESSION messages.
For console apps, you can use the SetConsoleCtrlHandler function to be notified of most cases of app termination (I don't have any experience with this so can't give many details).
For services, you can use the RegisterServiceCtrlHandler function in much the same way.
For all types of apps, if the app is terminated forcibly by another process via the TerminateProcess function, there is no way to get notified:
If a process is terminated by TerminateProcess, all threads of the process are terminated immediately with no chance to run additional code. This means that the thread does not execute code in termination handler blocks. In addition, no attached DLLs are notified that the process is detaching.

Creating a watchdog to capture minidumps

I'm trying to add the functionality of capturing mini-dumps when my program crashes. From what I've read, this is best achieved by use of another application (the watchdog) that is used to host the real application, and performs the dump.
From looking at posts such as this, I've come up with the following (both App and WatchDog are implemented in C++ using Win32):
When the watchdog starts, it creates 2 events, an ExitedOk event, and an Exception event, both of which are set to be inheritable and aren't signalled. It also creates an inheritable file mapping.
The watchdog then launches the "real app", and waits in a WaitOnMultipleObjects for either ExitedOk or Exception to be signalled.
When the app starts, it creates the same 2 events (it will inherit the handles)
The app is configured such that if it exits ok, it signals ExitedOk, or if an unhandled exception occurs, it stores the exception/thread info using the inherited filemapping, signals Exception, and then sleeps(Infinite).
If the WaitOnMultipleObjects in the watchdog is signalled with an ExitedOk, nothing happens. If it is signalled with an Exception, then it reads the exception/thread info using the filemapping, and then calls MiniDumpWriteDump.
Clearly the Sleep() is an issue. Is this best resolved through another event? Such that the App waits until the watchdog signals some "FinishedCreatingDump" event?
Secondly, I thought that the whole point of the watchdog was so that you weren't doing any work in the crashed process that is potentially unstable? If I'm understanding the workflow correctly, and that you do indeed need the SetEvent/OpenFileMapping/MapViewOfFile in the process that actually crashed, isn't that just as bad as calling MiniDumpWriteDump from it?

Understanding WaitForSingleObject and WaitForMultipleObject

I have a windows service where I am receiving http requests and launching a process for it which might run more than an hour . I need to get notified in main service when a process ends .And when service is ended i need to terminate all child processes . I understand that if I do waitforsingleobject it will hang on windows service until the process is completed , and no further http requests will be entertained ? I am doing following for now which works but its not correct approach .
if(CreateProcess( TEXT(EXEPATH),
procArguments,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi )
)
{
processHandles[processCount] = pi.hProcess;
processStreams[processCount] = eventId.c_str();
processCount++;
}
On Service stop I am doing this
for(int index=0;index<10;index++){
g_pAppLog->Log("Stop Process for processStreams[%d] %s\n",index,processStreams[index].c_str());
int terminationResult = TerminateProcess(processHandles[index],1);
}
The functions WaitForSingleObjectEx and WaitForMultipleObjectsEx allow you to specify a timeout, so that the function will not hang forever.
You can thus call the function in a loop, checking if the process has really terminated, or it's just a timeout expiration.
Anyway, you should not WaitFor anything, unless you have nothing better to do.
If you have a web server, you should listen to connection and spawn responding processes.
If you just want to check if a process terminated, you can call GetExitCodeProcess.
So, summing up, you might either:
Run a loop that:
accepts a request;
spawns a process;
checks if any of the previously created process terminated (without blocking);
Make a two-thread application, with one thread accepting requests, and the other one calling WaitForMultipleObjectsEx in a loop, and possibly handling children termination.
In your main service, you should create a thread to do that, so the main thread can still be running.. In this thread, you should use WaitforMultipleObjects to wait for all the child process to end, once a process is ended, the corresponding code will be execute.
Please check the MSDN for details
Do the waiting in a different thread than the one that is processing SCM requests. Use CreateEvent() to create a waitable manual-reset event, then have the waiting thread use WaitForMultipleObjects() to wait on both the event and the child process at the same time. WaitForMultipleObjects() will tell you which one is signaled first. When the service is being stopped, signal the event with SetEvent(). When the child process exits, its handle will be signaled. If the event gets signaled first, the waiting thread can call TerminateProcess() on the child process.

How to properly shutdown QProcess which I have created?

In my Qt C++ program I created a process as follows:
myProcess = new QProcess();
myProcess->start(programpath, arguments);
Terminating the process is handled as follows:
myProcess->terminate();
Terminating the child process with QProcess::kill(),terminate() or close() works, but I don't want to use it because it doesn't give the child process a chance to clean up before exiting.
Is there any other way to exit the process? Thanks!
The polite way would be for the parent process to politely ask the child process to go away. Then when the child process exits (of its own volition), the QProcess object will emit a finished(int, QProcess::ExitStatus) signal, and you can have a slot connected to that signal that will continue your process (e.g. by deleting the QProcess object at that time). (Or if you don't mind blocking your Qt event loop for a little while, you could just call waitForFinished() on the QProcess object after asking it to exit, and waitForFinished() won't return until the process has gone away or the timeout period has elapsed)
Of course for the above to work you need some way to ask the child process to exit. How you go about doing that will depend on what the child process is running. If you're lucky, you are in control of the child process's code, in which case you can modify it to exit in response to some action of the parent process -- for example, you could code the child process to exit when its stdin descriptor is closed, and have the parent process call closeWriteChannel() on the QProcess object to cause that to happen. Or if you're running under Linux/Unix you could send a SIGINT signal to the child process and the child process could set up a handler that would catch the signal and start an orderly shutdown. Or if you want something really stupid-quick and dirty, have the child process periodically check for the presence of a file at a well-known location (e.g. "/tmp/hey-child-process-PIDNUMBERHERE-go-away.txt" or something) and the parent process would create such a file when it wants the child to go away. Not that I'd recommend that last method as I don't think it would be very robust, except maybe as a proof of concept.
terminate actually gives the process an chance to clean up. The program being terminated just has to take that chance i.e. the system sents a SIGTERM and the application and it can ignore that and exit cleanly on its own. If this is still not nice enough then you have to implement your own way of asking the application to quit. Jeremy Friesner made some good successions. If the application code is not written by yourself you'll have to read the documentation for that program closer, maybe its documented how to do that.

How to check if a process is running or got segfaulted or terminated in linux from its pid in my main() in c++

I am invoking several processes in my main and I can get the pid of that processes. Now I want to wait until all this processes have been finished and then clear the shared memory block from my parent process. Also if any of the process not finished and segfaulted I want to kill that process. So how to check from the pid of processes in my parent process code that a process is finished without any error or it gave broke down becoz of runtime error or any other cause, so that I can kill that process.
Also what if I want to see the status of some other process which is not a child process but its pid is known.
Code is appreciated( I am not looking for script but code ).
Look into waitpid(2) with WNOHANG option. Check the "fate" of the process with macros in the manual page, especially WIFSIGNALED().
Also, segfaulted process is already dead (unless SIGSEGV is specifically handled by the process, which is usually not a good idea.)
From your updates, it looks like you also want to check on other processes, which are not children of your current process.
You can look at /proc/{pid}/status to get an overview of what a process is currently doing, its either going to be:
Running
Stopped
Sleeping
Disk (D) sleep (i/o bound, uninterruptable)
Zombie
However, once a process dies (fully, unless zombied) so does its entry in /proc. There's no way to tell if it exited successfully, segfaulted, caught a signal that could not be handled, or failed to handle a signal that could be handled. Not unless its parent logs that information somewhere.
It sounds like your writing a watchdog for other processes that you did not start, rather than keeping track of child processes.
If a program segfaults, you won't need to kill it. It's dead already.
Use the wait and waitpid calls to wait for children to finish and check the status for some idea of how they exiting. See here for details on how to use these functions. Note especially the WIFSIGNALED and WTERMSIG macros.
waitpid() from SIGCHLD handler to catch the moment when application terminates itself. Note that if you start multiple processes you have to loop on waitpid() with WNOHANG until it returns 0.
kill() with signal 0 to check whether the process is still running. IIRC zombies still qualify as processes thus you have to have proper SIGCHLD handler for that to work.