How to destroy object created in main() after SIGSEGV - c++

I would like to know if there is any trivial way of destroying an object that was created in main() after the application just crashed (or was interrupted, or some other. See the code:
#include <iostream>
#include <signal.h>
#include <stdlib.h>
class TestClass {
public:
TestClass() { std::cerr << "Constructor" << std::endl; }
~TestClass() { std::cerr << "Destructor" << std::endl; }
};
void signal_handler(int signum) {
std::cerr << "Signal caught " << signum << std::endl;
exit(1);
}
int main() {
TestClass a;
struct sigaction new_action, old_action;
new_action.sa_handler = signal_handler;
sigemptyset (&new_action.sa_mask);
new_action.sa_flags = 0;
sigaction (SIGSEGV, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN)
{
sigaction (SIGSEGV, &new_action, NULL);
}
// CRASH !!!
int* p = 0; *p = 0;
}
So, I install a signal handler, which upon execution shall do some cleanup, and just exit afterwards. Obviously, it is a big application, so I'd like to call the destructor of my classes which have created temporary files (theoretically speaking).
It would be easy to allocate it dynamically and in the signal_handler just free it (in order to call the destructor), but that involves some extra work.
And also, it could be a global object, but I want to avoid the global initialization order issue ...

You could try to orchestrate an orderly shutdown on SIGSEGV. It's not without its pitfalls, but start here: Is it possible to terminate only the one thread on receiving a SIGSEGV?
You could try to terminate the one offending thread in your signal handler, and set a global flag to say "We're screwed, time to shut down." Then in your main message loop, check the flag and break out if it's set.

Related

Willingly introducing a race condition on a 64-bit pointer value

I have an application object which can receive messages from multiple services running in multiple threads. The message gets dispatched internally by an instance of a dispatcher object in the threads of the services. The application can at any time change the current dispatcher. Dispatchers never get destroyed. The services never outlive the application.
Here's an example code
#include <iostream>
#include <thread>
#include <atomic>
#include <cstdlib>
#include <functional>
using namespace std;
using Msg = int;
struct Dispatcher
{
virtual ~Dispatcher() = default;
virtual void dispatchMessage(Msg msg) = 0;
};
struct DispatcherA : Dispatcher
{
void dispatchMessage(Msg msg)
{
cout << "Thread-safe dispatch of " << msg << " by A" << endl;
}
};
struct DispatcherB : Dispatcher
{
void dispatchMessage(Msg msg)
{
cout << "Thread-safe dispatch of " << msg << " by B" << endl;
}
};
struct Application
{
Application() : curDispatcher(&a) {}
void sendMessage(Msg msg)
{
// race here as this is called (and dereferenced) from many threads
// and can be changed by the main thread
curDispatcher->dispatchMessage(msg);
}
void changeDispatcher()
{
// race her as this is changed but can be dereferenced by many threads
if (rand() % 2) curDispatcher = &a;
else curDispatcher = &b;
}
atomic_bool running = true;
Dispatcher* curDispatcher; // race on this
DispatcherA a;
DispatcherB b;
};
void service(Application& app, int i) {
while (app.running) app.sendMessage(i++);
}
int main()
{
Application app;
std::thread t1(std::bind(service, std::ref(app), 1));
std::thread t2(std::bind(service, std::ref(app), 20));
for (int i = 0; i < 10000; ++i)
{
app.changeDispatcher();
}
app.running = false;
t1.join();
t2.join();
return 0;
}
I am aware that there is a race condition here. The curDispatcher pointer gets accessed by many threads and it can be changed at the same time by the main thread. It can be fixed by making the pointer atomic and explicitly loading it on every sendMessage call.
I don't want to pay the price of the atomic loads.
Can something bad happen of this?
Here's what I can think of:
The value of curDispatcher can get cached by a service and it can always call the same one, even if the app has changed the value. I'm ok with that. If I stop being ok with that, I can make it volatile. Newly created services should be ok, anyway.
If this ever runs on a 32-bit CPU which emulates 64-bit, the writes and reads of the pointer will not be instruction-level atomic and it might lead to invalid pointer values and crashes: I am making sure that this only runs on 64-bit CPUs.
Destroying dispatchers isn't safe. As I said: I'm never destroying dispatchers.
???

Why does thread.join fail when called in destructor of global variable

I reduced my problematic code to the following. I have a class C that runs a member function on its own thread. In the destructor of C I want to cleanly exit this thread. This works fine as long as c is defined within main (1), but not when it is a global variable (2). In the latter case, I see that the thread function returns but that the t.join() hangs.
#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>
using namespace std;
class C
{
public:
C()
{
stop = false;
t = thread(&C::ThreadFunc, this);
}
~C()
{
stop = true;
cv.notify_all();
if (t.joinable())
{
cout << "joining" << endl;
t.join();
cout << "joined" << endl;
}
}
private:
void ThreadFunc()
{
while (true)
{
unique_lock<mutex> lock(m);
cv.wait(lock, [&]{return stop;});
cout << "returning" << endl;
return;
}
}
thread t;
mutex m;
condition_variable cv;
bool stop;
};
C c; // does *not* work (2)
int _tmain(int argc, _TCHAR* argv[])
{
C c; // does work (1)
return 0;
}
The reason I use a global variable is that it is actually part of a dll. When the destructor is triggered from DllMain on DLL_PROCESS_DETACH, the same problem occurs.
Is there an explanation and a solution to this problem?
It's a deadlock. You are holding a lock that t requires in order to terminate while you are waiting for t to terminate.
Say as part of t's detach process, it makes some calls into the DLL. How can the DLL sensibly handle a request when there is a thread (the thread that called join) that is partially attached to it? Once you start detaching, and until you finish detaching, the DLL is an inconsistent state and cannot sensibly handle thread attach and detach operations.
You really don't want to try to join a thread while your process is in a context you can't control.

try/catch to avoid .stackdump

In the code below i use try/catch in the python module code. In the try block i have a simple error (memory access violation) and trying to catch the corresponding exception and to terminate the program quietly without generation of the .stackdump file. However the latter is still generated what implies that try/catch construct does not do its job. How could i avoid generating .stackdump file and exit the program without errors when the improper operation (like one in the code) is met?
P.S. i'm compiling the code in cygwin with gcc and boost.python
It is interesting that it doesn't work only in case x[3]=2, but works for all other cases: e.g. x[4]=2 or x[20]=2 or, obviously, x[2]=2.
#include <boost/python.hpp>
#include <iostream>
#include <iomanip>
using namespace std;
using namespace boost::python;
class Hello
{
std::string _msg;
public:
Hello(std::string msg){_msg = msg;}
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ exit(0); }
}
};
BOOST_PYTHON_MODULE(xyz)
{
class_<Hello>("Hello", init<std::string>())
.def("run",&Hello::run)
;
}
EDIT:
According to what Maciek has suggested i tried the following trick:
Make signal handling function to throw an exception, but not exit
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
throw 1;
// exit(0);
}
And now try to enclose a possibly problematic function in try/catch block (signal function is placed in class constructor):
class Hello
{
std::string _msg;
public:
Hello(std::string msg){
_msg = msg;
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
}
void set(std::string msg) { this->_msg = msg; }
std::string greet() { return _msg; }
void run(){
try{
double* x;
x = new double[3];
x[3] = 2.0;
delete [] x;
}catch(...){ cout<<"error in function run()\n"; exit(0); }
}
};
However such a trick doesn't work as i expected it produces the following output:
SIGNAL 6
terminate called after throwing an instance of 'int'
SIGNAL 6
terminate called recursively
SIGNAL 6
terminate called recursively
....
(and many more times the same)
So the exception is thrown, but everything finishes before it has been caught. Is there any way to let it be caught before terminating the process?
You can only catch exceptions that are thrown. An invalid pointer access doesn’t throw an exception, it simply causes undefined behaviour, and in your particular case it results in a stack dump.
If you want to catch such a situation situation, use std::vector and the at function to access items. This will throw std::out_of_range when used with an invalid index. However, it’s usually better to avoid the possibility of such accesses a priori since they are usually indicative of a bug in your program, and bugs should not be handled via exceptions, they should be removed from the code.
On linux core dumps are generated by signal handlers with default action set to core (SIGABRT, SIGSEGV, ...). If you want to avoid core dump you can always capture/ignore those signals. It should work on Cygwin stackdumps as well. But you will still probably get some nasty message as output.
EDIT:
#include <signal.h>
// [...]
void sig_action(int signo) {
std::cout << "SIGNAL " << signo << std::endl;
exit(0);
}
int main(int argc, char* argv[]) {
signal(SIGABRT, sig_action);
signal(SIGSEGV, sig_action);
Hello h("msg");
h.run();
}

How do you run a function on exit in C++

I have a function that I want to run whenever my program exits:
void foo() {
std::cout<< "Exiting" << std::endl;
}
How do I register it to be run whenever the program exists, regardless of when and why it exits - due to signal, exit() call, etc?
You can use the aptly named std::atexit function in the cstdlib header:
#include <cstdlib>
void exiting() {
std::cout << "Exiting";
}
int main() {
std::atexit(exiting);
}
The system will maintain a stack of functions registered with atexit and call them each in the reverse order of their registration when either the exit function is called, or the program returns from main. You can register at least 32 functions this way.
I am answering as a Linux user, but all of this should apply to windows.
I had this similar question, so hopefully I can sum up previous answers and add my two cents.
Signals and abort(): ^C and ^Z can be "intercepted" to call your function before exiting, presumably with exit(). Signals SIGQUIT AKA ^\ and SIGKILL which has no key stroke cannot be intercepted. Here's an example for using the csignal header and a C++ lambda.
#include <iostream>
#include <csignal>
#include <cstdlib>
using namespace std;
int main()
{
//signal requires lam take an int parameter
//this parameter is equal to the signals value
auto lam =
[] (int i) { cout << "aborting" << endl; exit(0); };
//^C
signal(SIGINT, lam);
//abort()
signal(SIGABRT, lam);
//sent by "kill" command
signal(SIGTERM, lam);
//^Z
signal(SIGTSTP, lam);
while(1)
{
}
return 0;
}
Exit: Since I used exit() in my examples above, care must be taken here. If the function being run is a clean-up function that only needs to run once, perhaps a static variable has_run could be used. Or in the example above, raise() a signal that you can't intercept. But those tend to come with core dumps which just feels dirty. Your choice, here. An example follows
#include <cstdlib>
#include <iostream>
using namespace std;
int main()
{
//called with no parameters
auto lam = [] () { cout << "at exit"; };
atexit(lam);
return 0;
}
Take note that c++11 added a quick_exit which has an accompanying at_quick_exit which act the same as above. But with quick_exit no clean up tasks are performed. In contrast, with exit object destructors are called and C streams are closed, with only automatic storage variables not getting cleaned up.
You could put it in the destructor of a class with a global instance.
class SomeGlobalStuff {
~SomeGlobalStuff() {
foo();
}
static SomeGlobalStuff instance;
};
// putting this in a single compilation unit.
SomeGlobalStuff SomeGlobalStuff::instance instance;
But like any other method, you have to remember that you cannot use any data if you cannot garantee that it still exists. Deallocation of global objects is done in a arbitrary order, so basically, you cannot use std::cout in the foo() function. atexit() is worse in this regard, because whether it executes before or after destruction of global objects depends on the compiler and compiler options.
And anyway, you still have to handle signals correctly. You have to choose which signals to handle and which to not handle (you most likely don't want to handle SIGSEGV). You cannot escape signal handling. And remember that signals may interrupt your program at any time (unless masked) so your data structures might be in a arbitrary state, in the middle of an update.
The only way (in Unix and Unix-like operating systems) to regain control after a process exits is to wait(2) for it. Short of a powerfail, kernel panic, or forced reboot, this should work:
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
int AtExit() {
pid_t pid = fork();
if(pid < 0) return pid;
if(pid == 0) return pid;
pid = waitpid(pid, 0, 0);
return pid;
}
int main () {
if(AtExit()) {
std::cout << "Exiting\n";
return 0;
}
std::cout << 7 << "\n";
}

How can I handle interrupt signal and call destructor in c++? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is destructor called if SIGINT or SIGSTP issued?
My code like this:
#include <iostream>
#include <signal.h>
#include <cstdlib>
void handler(int) {
std::cout << "will exit..." << std::endl;
exit(0);
}
class A {
public:
A() {std::cout << "constructor" << std::endl;}
~A() {std::cout << "destructor" << std::endl;}
};
int main(void) {
signal(SIGINT, &handler);
A a;
for (;;);
return 0;
}
When I pressed Ctrl-C, it printed:
constructor
^Cwill exit...
There is no "destructor" printed.
So, how can I exit cleanly?
With difficulty. Already, the code you've written has undefined
behavior; you're not allowed to output to a stream in a signal handler;
for that matter, you're not allowed to call exit either. (I'm basing
my assertions here on the Posix standard. In pure C++, all you're
allowed to do is assign to a variable of sig_atomic_t type.)
In a simple case like your code, you could do something like:
sig_atomic_t stopFlag = 0;
void
handler( int )
{
stopFlag = 1;
}
int
main()
{
signal( SIGINT, &handler );
A a;
while ( stopFlag == 0 ) {
}
std::cout << "will exit..." << std::endl;
return 0;
}
Depending on the application, you may be able to do something like this,
checking the stopFlag at appropriate places. But generally, if you
try this, there will be race conditions: you check stopFlag before
starting an interuptable system call, then do the call; the signal
arrives between the check and the call, you do the call, and it isn't
interrupted. (I've used this technique, but in an application where the
only interruptable system call was a socket read with a very short
timeout.)
Typically, at least under Posix, you'll end up having to create a signal
handling thread; this can then be used to cleanly shut down all of the
other threads. Basically, you start by setting the signal mask to block
all signals, then in the signal handling thread, once started, set it to
accept the signals you're interested in and call sigwait(). This
implies, however, that you do all of the usual actions necessary for a
clean shutdown of the threads: the signal handling thread has to know
about all other threads, call pthread_cancel on them, etc., and you're
compiler has to generate the correct code to handle pthread_cancel, or
you need to develop some other means of ensuring that all threads are
correctly notified. (One would hope, today, that all compilers handle
pthread_cancel correctly. But one never knows; doing so has
significant runtime cost, and is not usually needed.)
You need to exit from the main function's scope to have the destructor working:
#include <iostream>
#include <signal.h>
#include <cstdlib>
bool stop = false;
void handler(int) {
std::cout << "will exit..." << std::endl;
stop = true;
}
class A {
public:
A() {std::cout << "constructor" << std::endl;}
~A() {std::cout << "destructor" << std::endl;}
};
int main(void) {
A a;
signal(SIGINT, &handler);
for (;!stop;);
return 0;
}
It's because the context of the normal code and the signal handler is different. If you put the variable a in global scope (i.e. outside of any function) you will see that the destructor is called properly.
If you want to handle cleaning up yourself (instead of letting the run-time and OS handle it), you can have a conditional loop, something like this:
bool keep_running = true;
void handler(int) {
std::cout << "will exit..." << std::endl;
keep_running = false;
}
int main(void) {
signal(SIGINT, &handler);
A a;
while (keep_running);
return 0;
}
Memory should be freed anyway. but if you've got code to be handled, I guess you'd have to track all your objects and then destroy them as needed (e.g. having the constructor adding them to a std::set, while the destructor removes them again). However this wouldn't ensure proper order of destruction (which might require some more complex solution).
You could as well use your signal handler to set some flag that will leave the infinite loop (or whatever you're doing in your main loop) instead of simply terminating using exit().
exit terminates the process almost immediately; in particular, objects with automatic storage duration are not destroyed. Streams are also flushed and closed, but you're not allowed to touch streams from inside a signal handler. So...
Simply don't call exit from a signal handler; set some atomic flag to instruct the loop to end instead.
#include <iostream>
#include <signal.h>
#include <cstdlib>
sig_atomic_t exitRequested = 0;
void handler(int) {
std::cout << "will exit..." << std::endl;
exitRequested = 1;
}
struct A {
A() { std::cout << "constructor" << std::endl; }
~A() { std::cout << "destructor" << std::endl; }
};
int main() {
signal(SIGINT, &handler);
A a;
for (; !exitRequested; );
}