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.
SIGTERM (signal 15) is used in Unix-based operating systems, such as Linux, to terminate a process. The SIGTERM signal provides an elegant way to terminate a program, giving it the opportunity to prepare to shut down and perform cleanup tasks, or refuse to shut down under certain circumstances.
exit() closes all files and sockets, frees all memory and then terminates the process.
kill ends a process by sending it a signal. The default signal is SIGTERM. kill is a built-in shell command. In the tcsh shell, kill [-signal] %job|pid … sends the specified signal (or if none is given, the TERM (terminate) signal) to the specified jobs or processes.
SIGTERM. (signal 15) is a request to the program to terminate. If the program has a signal handler for SIGTERM that does not actually terminate the application, this kill may have no effect. This is the default signal sent by kill.
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() )
{
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With