Suppose we have small program, written in C++, which looks like below.
This program itself intentionally does NOT perform signal handling via WinAPI call SetConsoleCtrlHandler - it's important part of question.
#include <stdio.h>
#include <stdlib.h>
int main() {
while(true) {
int status = system("EXTERNAL COMMAND");
printf("RESULT STATUS = %d\n", status);
}
}
When Ctrl+C key combination have been pressed in terminal, program above have quite different behavior depend on which "EXTERNAL COMMAND" had been invoked
1) If external command is pause, program will stand in infinite loop, invoking pause command step by step, and will print "RESULT STATUS = 0" many times, while not terminated forced via process kill.
2) If external command in choice, program will terminate immediately after Ctrl+C pressure. It will not print anything and does not return from system call.
3) If external command is set /P VAR=, program has much interesting behavior. When Ctrl+C pressed, program prints `"RESULT STATUS = 1" and continue working until first async call is performed.
First and second case can be explained in following manner. Terminal windows is proxt between user input and target program, so when user presses Ctrl+C, terminal window perform dispatch signal itself to target process.
So some subprocesses can take manually terminal handler via hConsole = GetStdHandle(STD_OUTPUT_HANDLE) and perform own signal handling. Another subprocess does not do this, so signal passed into parent process and terminate it.
But third case causes big question. If child process intercepts SIGINT, why parent process perform terminating after first async call. If not, why it does not terminate immediately and why and how it prints `"RESULT STATUS = 1" and continue working.
Thanks
There are no Unix signals in Windows, at least not from the kernel. That said, Windows and the Windows API are fundamentally based on the C programming language, which, having been developed in tandem with Unix, does require six signals. The C runtime in Windows emulates SIGABRT and SIGTERM within process (e.g. for use with C raise). For SIGSEGV, SIGILL, and SIGFPE it uses an OS exception handler. In a console application, standardSIGINT and non-standard SIGBREAK are associated with the C runtime's console control handler, which is usually the first handler registered via SetConsoleCtrlHandler. CTRL_C_EVENT is mapped to the SIGINT signal handler, and all others (CTRL_BREAK_EVENT, CTRL_CLOSE_EVENT) are mapped to the SIGBREAK handler.
Console control events are sent by the console host (conhost.exe), which implements this by having the session server (csrss.exe) create a thread in a client process. This thread begins at the undocumented CtrlRoutine function in kernelbase.dll, which walks the registered control handlers until one of them handles the event by returning true. If none of them handles the event, the default handler calls ExitProcess(STATUS_CONTROL_C_EXIT). Note that SetConsoleCtrlHandler(NULL, TRUE) sets a flag that makes CtrlRoutine ignore CTRL_C_EVENT, and this flag is inherited by child processes and enabled by default when a process is created with the flag CREATE_NEW_PROCESS_GROUP. Also, for CTRL_CLOSE_EVENT, the session server gives each process 5 seconds to handle the event and exit on its own, else it terminates the process forcefully.
To understand what's happening with CMD's internal PAUSE command, see SetConsoleMode, and, in particular, ENABLE_PROCESSED_INPUT. PAUSE calls C _getch, which temporarily sets the console input mode to 0. With the processed-input mode disabled, Ctrl+C is simply read as "\x03" instead of generating a CTRL_C_EVENT.
Related
I read some documentation but it isn't clear enough to me. I know that both "end" a process and that kill() is meant to force it to end, but what is terminate() supposed to do then?
Dunno what's not clear if you have written:
void QProcess::kill()
Kills the current process, causing it to exit immediately.
On Windows, kill() uses TerminateProcess, and on Unix and OS X, the SIGKILL signal is sent to the process.
http://doc.qt.io/qt-5/qprocess.html#kill
void QProcess::terminate()
Attempts to terminate the process.
The process may not exit as a result of calling this function (it is given the chance to prompt the user for any unsaved files, etc).
On Windows, terminate() posts a WM_CLOSE message to all toplevel windows of the process and then to the main thread of the process itself. On Unix and OS X the SIGTERM signal is sent.
Console applications on Windows that do not run an event loop, or whose event loop does not handle the WM_CLOSE message, can only be terminated by calling kill().
http://doc.qt.io/qt-5/qprocess.html#terminate
So, basically terminate() is less brutal, but does not guarantee that process will be terminated.
On Unix terminate() uses SIGTERM signal, while kill() sends SIGKILL to the process. The difference between them is that SIGTERM can be caught by a process, which allows it to perform cleanup etc. SIGTERM can be ignored. SIGKILL will literally kill process, process can not ignore it.
On Windows WM_CLOSE message is posted, when you call terminate(), so application can also gracefully handle it. kill() calls TerminateProcess(), which is more or less Windows equvalent of SIGKILL.
I think terminate() SIGTERM and WM_CLOSE could be handled by Qt and translated into normal Qt events, but you have to try it yourself. You can of course handle them by system specific functions.
"what causes terminate() to not exit the process."
It is you, because you can catch terminate() signals/messages and do whatever you want, or it can be user of your application if he is prompted if he really wants to quit app. Yet another resource on WM_CLOSE.
Is it possible by any means to brute force momentally pause the execution of an external program? Or something that archieves a similar effect.
I've seen this beforce, a 3rd party software that once came with my Asus laptop, however Im courious on how they managed it.
You can send signals to process. Depending on your operating system, they mean different things. A program which catches a signal may terminate, sleep or continue.
Here is a manual about signals: http://www.cs.cf.ac.uk/Dave/C/node24.html
In short:
Use kill (dont be scared, the functions is just called kill and wont terminate anything on its own) to send a signal to a known process id. You can get process ids in linux with ps aux in terminal. This Linux signal looks promising for you:
SIGCONT 19 /* continue a stopped process */
int kill(int pid, int signal)
a system call that send a signal to a process, pid. If pid is greater than zero, the signal is sent to the process whose process ID is equal to pid. If pid is 0, the signal is sent to all processes, except system processes.
I don't know much about Windows SIGNAL Codes, but it should work similar. Don't know if they are handling the signal codes different then Linux.
There is also: signal (int number, functionPointer) to call a function, if your programm gets a specific signal.
I don't know about bruteforce, but you can probably just set a debug break in a program and that would pause it.
I have written a C++ program and I am executing in the gnome terminal (I am on Ubuntu). I press Ctrl + Z, which suspends the process. Later on, I execute % on the same terminal, which resumes execution.
From what I've read, Ctrl+Z sends a TSTP signals to the process, which tells it to stop execution. But TSTP is polite, in the sense that the process is allowed to continue until it decides it can stop. In my C++ program code, I didn't do anything to explicitly deal with TSTP signals. So, my question is, what things inside my C++ code will continue running in spite of the TSTP signal? For example, if I have a file stream open, will it wait until it is closed? I expect an overall answer, not too deep or covering all the details. I just want an idea of how this happens.
Your program continues running while the SIGTSTP handler executes. Since you haven't set one up, you get the default signal handling behavior, which is for the process to be stopped.
While your process is stopped, it simply isn't scheduled for execution. Files don't get closed, nor is stopping delayed until files get closed (unless done in the signal handler).
This website looks like it has a helpful explanation of how a handler can be installed to perform some tasks and then have the default stopping behavior:
http://man7.org/tlpi/code/online/dist/pgsjc/handling_SIGTSTP.c.html
I am currently using a script to call pkill to terminate my C++ program.
However i noticed that the destructors were not called from my traces when using pkill.
Is there another good way that i can exit the program gracefully?
pkill seems kind of untidy and some logs in the buffer do not get recorded. I'd like to be able to flush on my fstream and to close all resources programatically (instead of relying on the O/S to clean up my mess).
The application runs 24/7 without any problem, the only time i want to stop it is during maintenance. The application does not have any user interface for me to type exit.
You do it by defining a signal handler for SIGTERM along these lines:
Somewhere in your include block:
#include <signal.h>
#include <stdio.h>
Yes, we're doing i C style!
Somewhere in the initialization part of your code:
signal (SIGTERM, handler);
and then define the signal handlers code (flush everything, etc):
void handler(int num)
{
// we might use this handler for many signals
switch (num)
{
case SIGTERM:
// clean up code.
break;
}
}
Now when you run pkill <app>, where <app> is the name of the executable, the code for handler() will run.
Without switches, the default SIGTERM signal will be sent to the application. Should you choose to use a different signal you would have to make sure you send the same signal as you "catch" in the handler().
Relevant information can be found by man 7 signal and of course, man kill.
In addition to Zrvan's answer, be aware that only a restricted set of functions can be safely called from a signal handler. The signal(7) man page, and the Posix standards, require that only Async-signal-safe functions can be called directly or indirectly inside a signal handler. Note that printf or malloc are not safe inside a signal handler. Signal handler's code is tricky to write (and you cannot debug it easily, because signal sending is non-reproducible).
As the Glibc documentation suggests, your signal handler could just set a volatile sig_atomic_t variable, which your main loop[s] would test and handle.
You could also decide, if you application is event based, that some socket or named pipe is dedicated to control it. That event loop (perhaps using select(2) or poll(2), or even pselect or ppoll) could handle the control message on the pipe or socket.
You may be interested by event looping libraries like libevent. You might also use an HTTP server library like onion or Wt. You could also be interested by SNMP or D-bus.
A trick to overcome the limitation of signal handlers is to have them write on a pipe to the same process, as e.g. Qt's doc is suggesting. Then the event loop would handle reading on that pipe.
If your application is multi-threaded, signal handling is more tricky. Some signals are delivered to an individual thread.
Unless you modify the target application, I don't see a way.
Consider the following:
int main()
{
MyClass a;
while ( true )
{
}
}
You'd have to tell the program to exit the loop. But unless you have some signal handling mechanism on your app, that seems impossible.
You'd need something like:
int main()
{
MyClass a;
while ( !killSignalReceived() )
{
}
}
The best way is to handle a signal in the program, and then send that signal using kill. In the signal handler, mark a flag that will cause the main loop to end.
Sometimes when I am debugging I get message like this.
Program received signal SIG44, Real-time event 44.
What does it means?
Thank you.
EDIT :
Platform is linux
A signal is a message sent by the kernel to a process in order to notify the process that event of some kind has occurred in the system.
Usual signals on linux are for example SIGINT (value 2, interrupt from keyboard) or SIGKILL ( value 9, kill a program).
Signals are received either when the kernel detects a system event (like division by zero is SIGFPE, value 8) or when a process invokes the kill() function to explicitly tell the kernel to send a signal to a process (or to the process itself that called the kill() ).
A signal can often be caught by the process in order to do something.
So to answer to your question, the code is most likely calling the kill() function and sending it a signal with value 44 when something happens. Since you are getting that message, it means that the process has received the signal and is going to exit or do what is written in the code in case that signal comes.
Unlike standard signals, real-time
signals have no predefined meanings:
the entire set of real-time signals
can be used for application-defined
purposes. (Note, however, that the
LinuxThreads implementation uses the
first three real-time signals.)
Source for the quote here
The GNU C++ library uses SIG44 to awaken sleeping threads when signalling condition variables.