I have a class with a user-defined destructor. If the class was instantiated initially, and then SIGINT is issued (using CTRL+C in unix) while the program is running, will the destructor be called? What is the behaviour for SIGSTP (CTRL + Z in unix)?
No, by default, most signals cause an immediate, abnormal exit of your program.
However, you can easily change the default behavior for most signals.
This code shows how to make a signal exit your program normally, including calling all the usual destructors:
#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cstring>
#include <atomic>
std::atomic<bool> quit(false); // signal flag
void got_signal(int)
{
// Signal handler function.
// Set the flag and return.
// Never do real work inside this function.
// See also: man 7 signal-safety
quit.store(true);
}
class Foo
{
public:
~Foo() { std::cout << "destructor\n"; }
};
int main(void)
{
struct sigaction sa;
memset( &sa, 0, sizeof(sa) );
sa.sa_handler = got_signal;
sigfillset(&sa.sa_mask);
sigaction(SIGINT,&sa,NULL);
Foo foo; // needs destruction before exit
while (true)
{
// do real work here...
sleep(1);
if( quit.load() ) break; // exit normally after SIGINT
}
return 0;
}
If you run this program and press control-C, you should see the word "destructor" printed.
Be aware that your signal handler function (got_signal) should rarely do any work, other than setting a flag and returning quietly, unless you really know what you are doing. See also: https://man7.org/linux/man-pages/man7/signal-safety.7.html
Most signals are catchable as shown above, but not SIGKILL, you have no control over it because SIGKILL is a last-ditch method for killing a runaway process, and not SIGSTOP which allows a user to freeze a process cold. Note that you can catch SIGTSTP (control-Z) if desired, but you don't need to if your only interest in signals is destructor behavior, because eventually after a control-Z the process will be woken up, will continue running, and will exit normally with all the destructors in effect.
use of deleted function
for the quit = false
line. You have to do quit(false)
instead of quit = false
. Also worth noting that this code doesn't work on Windows; you have to use SetConsoleCtrlHandler()
. –
Sporulate If you do not handle these signals yourself, then, no, the destructors are not called. However, the operating system will reclaim any resources your program used when it terminates.
If you wish to handle signals yourself, then consider checking out the sigaction
standard library function.
Let's try it:
#include <stdio.h>
#include <unistd.h>
class Foo {
public:
Foo() {};
~Foo() { printf("Yay!\n"); }
} bar;
int main(int argc, char **argv) {
sleep(5);
}
And then:
$ g++ -o test ./test.cc
$ ./test
^C
$ ./test
Yay!
So I'm afraid not, you'll have to catch it.
As for SIGSTOP
, it cannot be caught, and pauses the process until a SIGCONT
is sent.
© 2022 - 2024 — McMap. All rights reserved.
quit
should bevolatile std::sig_atomic_t
. It's UB to usebool
for that purpose. – Fougere