Reputation: 574
Is there any way to send a signal to a process (in Linux), that results in a termination of the process after going through the "atexit-functions" (in this case: void shutdownEngines()
)? Using "pkill name" does not work.
#include <cstdlib>
void shutdownEngines() {/*is not executed by "pkill name"*/}
int main() {
atexit(shutdownEngines);
while(true)
doStuff();
}
Usage: I'm currently programming a robot. Every time I want to test it, I'll start the program and terminate it with "pkill name
", but "shutdownEngines
" isn't called and the robot keeps moving, falling off the table etc.
I know I could do "pkill name; ./shutdownEngines.sh
", but this would be very bad style in my case (the numbers of the gpio pins connected to the engines are defined in a header file of the main program (the source code of the main program is not on the robot but on my computer). Making sure that there's always a "shutdownEngines.sh
" program/script with the right pins on every robot would be very complicated.
The following code works perfectly:
#include <iostream>
#include <csignal>
#include <cstdlib>
void signalHandler(__attribute__((unused)) const int signum) {
exit(EXIT_FAILURE);
}
void driverEpilog() {
std::cout << "shutting down engines...";
//drv255(0,0);
}
int main() {
signal(SIGTERM, signalHandler);
atexit(driverEpilog);
while(true)
system("sleep 1");
}
Upvotes: 3
Views: 3595
Reputation: 140178
from the man page of atexit
:
Functions registered using atexit() (and on_exit(3)) are not called if a process terminates abnormally because of the delivery of a signal.
atexit
is called when your main routine returns or when you call exit
, not on a signal.
When you call pkill
you're sending a SIGTERM
signal. Handle this signal with signal
or sigaction
instead (define handlers on SIGTERM
, SIGINT
, SIGFPE
, ...) to stop the engines before exiting your program.
Example lifted from GNU C library documentation:
void
termination_handler (int signum)
{
struct temp_file *p;
for (p = temp_file_list; p; p = p->next)
unlink (p->name); // don't delete files, stop your engines instead :)
}
int
main (void)
{
…
struct sigaction new_action, old_action;
/* Set up the structure to specify the new action. */
new_action.sa_handler = termination_handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGINT, &new_action, NULL);
sigaction (SIGHUP, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGHUP, &new_action, NULL);
sigaction (SIGTERM, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
sigaction (SIGTERM, &new_action, NULL);
…
}
(of course, no handler can handle the SIGKILL
"signal", which tells the OS to remove your process from the active process list, without further notice!)
Upvotes: 5