How to write signal handler for sigabrt signal? - c++

I am trying to delete an already deleted object and I am getting a SIGABRT signal.
I know this signal aborts my program, but I want to catch this signal in a signal handler and display the message that I am deleting an already deleted object...
Here is the code I have tried, but it doesn't seem to work.
Please help me figure out what's wrong in it?
using namespace std;
class myclass
{
public:
myclass() { cout <<"myclass constructed\n"; }
~myclass() { cout <<"myclass destroyed\n"; }
};
void func(int);
int main (void)
{
signal(SIGABRT,func);
myclass * pt;
pt = new myclass[3];
delete[] pt;
delete[] pt;
return 0;
}
void func(int)
{
signal(SIGABRT,func);
cout << "trying to delete unallocated memory, exiting....\n";
exit(0);
}

The C standard says (section 7.14, paragraph 4 of both C99 and C11):
An implementation need not generate any of these signals, except as a result of explicit
calls to the raise function.
The C++ standard doesn't give any additional additional guarantees.
POSIX says:
The abort() function shall cause abnormal process termination to occur, unless the signal SIGABRT is being caught and the signal handler does not return.
The abnormal termination processing shall include the default actions defined for SIGABRT and may include an attempt to effect fclose() on all open streams.
The SIGABRT signal shall be sent to the calling process as if by means of raise() with the argument SIGABRT.
The status made available to wait() or waitpid() by abort() shall be that of a process terminated by the SIGABRT signal. The abort() function shall override blocking or ignoring the SIGABRT signal.
So, yeah, you have no basis for expecting to see a SIGABRT at all; you're lucky you aren't encountering nasal demons!

Related

Exception not caught after signal

I try to catch a termination signal to my code to write a restart file before exiting. My solution is based on this answer.
#include <exception>
#include <csignal>
#include <iostream>
class InterruptException : public std::exception
{
public:
InterruptException(int _s) : signal_(_s) { }
int signal() const noexcept
{
return this->signal_;
}
private:
int signal_;
};
/// method to throw exception at signal interrupt
void sig_to_exception(int s)
{
throw InterruptException(s);
}
int main()
{
// activate signal handling
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = sig_to_exception;
sigemptyset(&sigIntHandler.sa_mask);
sigIntHandler.sa_flags = 0;
sigaction(SIGINT, &sigIntHandler, NULL);
try
{
for (std::size_t i = 0; i < 100000000; ++i)
{
std::cout << i << std::endl;
}
}
catch (const InterruptException& e)
{
std::cout << "Received signal " << e.signal() << std::endl;
std::exit(1);
}
catch(...)
{
std::cout << "Other catch!" << std::endl;
}
}
The exception gets thrown fine, however, my catch block does not catch it. The program terminates with an uncaught exception InterruptException. I tried with clang and gcc on MacOS. Any idea why the exception is not caught correctly?
Thanks
Output when compiled with g++ 7.3.0:
terminate called after throwing an instance of 'InterruptException'
what(): std::exception
Abort trap: 6
Output when compiled with Apple LLVM 9.0.0
libc++abi.dylib: terminating with uncaught exception of type InterruptException: std::exception
PS: It seems when I compile with Apple LLVM the exception gets caught sometimes, but not all the time, which makes this even weirder.
There is very little that you can reliably do in a signal handler. In particular, you cannot throw an exception. The code in the question (and the "answer" that it links to) relies, at best, on compiler/OS-specific behavior. For the limits on what you can do in a signal handler, see this.
Note that the link above refers to signal, which is standard C. sigaction is not standard C, it's POSIX, and the C++ language definition doesn't impose any requirements on a program that uses it.
On most system the stack frame used by the signal handler is not a standard function stack frame as defined by the compiler for function calls.
So throwing out of a sig handler is not supported.
Stack frame for signal handling in the Linux Kernel
From the discussion in the linked question, on a linux system they are not even using the same stack for the stack frame and returning requires jumping back to a system function to restore the original user stack.
Unless the OS is specifically designed to handle exceptions then this is not going to work.
The rule of thumb for signal handlers is to do as little as possible in a signal handler. Set a global flag that can be detected by your normal code then check that flag periodically in your normal code to see when the signal has happened.

How to print something when runtime error occurs somewhere in my C++ code?

What normally happens is when code faces Runtime error , it simply terminates with runtime flag , what i intend to do is print a custom message before termination & i wish to 'return 0' ,ie terminate code normally after printing custom message as if runtime never happened .
Any idea how to do it?
There are different reasons, why a programm might terminate.
First: An uncaught Exception was thrown. If that is, what you are looking for, then follow the advice, Paul Evans has given. With C++11, you might want to call get_terminate(), and call the returned teminate handler at the end of your new teminate handler:
terminate_handler old_terminate_handler = nullptr;
void new_terminate_handler() {
std::cerr << "terminate due to error" << std::endl;
if( old_terminate_handler != nullptr ) {
old_terminate_handler();
} else {
std::abort();
}
}
int main(int, char**) {
old_terminate_handler = get_terminate();
set_terminate(new_terminate_handler);
}
Second: a signal was received, that would normaly terminate the program. Install a signal handler to catch it:
void sig_handler(int signal) {
new_terminate_handler();
}
// ...
std::signal(SIGTERM, sig_handler);
std::signal(SIGSEGV, sig_handler);
std::signal(SIGINT, sig_handler);
// ...
Third: The operating system might simply decide to kill the process. That is either done by a normal signal signal (e.g. SIGTERM), or by a signal, that can not be handled (e.g. SIGKILL) In the second case, you have no chance to notice that inside the programm. The first case is already covered.
First define your custom terminate handler, something like:
void f() {
std::cout << \\ your custom message
}
then you want to call:
std::terminate_handler set_terminate( std::terminate_handler f );
to set up your function f as the terminate handler.

How can I programmatically get the default behavior of sigterm inside a custom signal handler?

Based on man -S 7 signal, when a program which has not defined a signal handler receives SIGTERM, the default action is to Term.
I am registering a custom signal handler for SIGTERM, but I want the final statement (after specific cleanup is done) in my custom handler to be a function call that achieves the exact same effect as Term.
What is the correct function to call here?
I have tried exit(0), but that causes the destructors of statically initialized objects to be called, which does not match the behavior of Term. I have also tried abort(), and that causes a core dump.
In the following example, I am using the lifetime of statically allocated objects as an illustrative example, but my question is more broad than just the lifetime of statically allocated objects.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
struct Foo{
~Foo() {
fprintf(stderr, "Dying!\n");
}
Foo() {
fprintf(stderr, "Constructing!\n");
}
};
Foo foo;
void sig_handler(int signo) {
// exit(0);
// abort();
}
int main(){
// signal(SIGTERM, sig_handler);
while(1);
}
Here are various behaviors:
The code as-is will print Constructing! but not Dying! if SIGTERM is received.
When the //signal line is commented back in, and exit(0) is commented back in, the code will print both Constructing! and Dying!
When exit(0) is commented out, and abort() is commented in, the program will output Constructing! followed by Aborted (core dumped).
To ask my question in another way, I want to know what I need to put in the body of signal_handler in order to mimic behavior 1 in every way (not just the output I have shown).
signal(SIGTERM, SIG_DFL);
kill(getpid(), SIGTERM);
There is no function call, as termination upon signals is handled by the kernel, not the user process, but this will restore the default handler, then send a signal to yourself, which kills the process just like the signal had never been caught.
You can call _exit instead of exit , which should exit the process without running global destructors.

How to ensure popen()ed process runs destructors on exit?

If I have a pipe to run some command, the piped command needs to do some cleanup, however, if the processes that started the pipe has an error, the piped command is not cleaning up. Is the piped command getting SIGPIPE in this case? How can I ensure cleanupPipe destructor is always run? When the errorOccurred exception is thrown, I am seeing that cleanupPipe destructor is not run. I have SIGPIPE handler set up to throw an exception, so if SIGPIPE is the result, I would expect my destructor to be run when the SIGPIPE results in thrown exception unwinding the stack.
void
testCase() {
class cleanup {
public:
cleanup(FILE *pipe)
: _pipe(pipe) {
}
~cleanup() {
::pclose(_pipe);
}
private:
FILE *_pipe;
};
string cmd("runMyCommandImplementationHere argsHere");
FILE *pipePtr = ::popen(cmd, "w");
cleanup cleanUpPipe(pipePtr);
// Normally, write data to pipe until process in pipe gets all the data it
// needs and exits gracefully.
for (;;) {
if (someErrorOccured()) {
// When this error occurs, we want to ensure cleanupPipe is run in piped
// process.
throw errorOccurred(status);
}
if (finishedWritingData()) {
break;
}
writeSomeDataToPipe(pipePtr);
}
}
void
myCommandImplementationHere() {
class cleaupPipe {
public:
cleanupPipe(const string &filename)
: _filename(filename) {
}
~cleanupPipe() {
::unlink(_filename.c_str());
}
private:
string _filename;
};
string file("/tmp/fileToCleanUp");
cleanupPipe cleanup(file);
doSomeWorkOnFileWhileReadingPipeTillDone(file);
}
Throwing an exception in a signal handler is a very bad idea. Signal handlers must be asynchronous-safe. To make matters worse, signal handlers run in which is essentially a different thread of execution than your mainline code. It is best to keep your signal handlers small and very primitive. For example, make the SIGPIPE handler set some volatile global variable that indicates that SIGPIPE occurred and test for that as an error condition in your mainline code.
A couple of other comments:
You should check the return status when dealing with C functions such as popen, pclose, and write. You aren't doing so on your call to popen or pclose, at least not in the sample code.
Why the asymmetry in class Cleanup? The constructor receives an already-constructed FILE pointer, but the destructor destroys it via pclose. IMO it would be better if the constructor calls popen, taking the command string as an argument to the constructor.
Addendum
Perhaps even better than creating a handler for SIGPIPE that sets some global variable is to set the handler for SIGPIPE to ignore, and then check for an EPIPE error from your writes to the pipe.

Inject runtime exception to pthread sometime fails. How to fix that?

I try to inject the exception to thread using signals, but some times the exception is not get caught. For example the following code:
void _sigthrow(int sig)
{
throw runtime_error(strsignal(sig));
}
struct sigaction sigthrow = {{&_sigthrow}};
void* thread1(void*)
{
sigaction(SIGINT,&sigthrow,NULL);
try
{
while(1) usleep(1);
}
catch(exception &e)
{
cerr << "Thread1 catched " << e.what() << endl;
}
};
void* thread2(void*)
{
sigaction(SIGINT,&sigthrow,NULL);
try
{
while(1);
}
catch(exception &e)
{
cerr << "Thread2 catched " << e.what() << endl; //never goes here
}
};
If I try to execute like:
int main()
{
pthread_t p1,p2;
pthread_create( &p1, NULL, &thread1, NULL );
pthread_create( &p2, NULL, &thread2, NULL );
sleep(1);
pthread_kill( p1, SIGINT);
pthread_kill( p2, SIGINT);
sleep(1);
return EXIT_SUCCESS;
}
I get the following output:
Thread1 catched Interrupt
terminate called after throwing an instance of 'std::runtime_error'
what(): Interrupt
Aborted
How can I make second threat catch exception?
Is there better idea about injecting exceptions?
G++ assumes that exceptions can only be thrown from function calls. If you're going to violate this assumption (eg, by throwing them from signal handlers), you need to pass -fnon-call-exceptions to G++ when building your program.
Note, however that this causes G++ to:
Generate code that allows trapping instructions to throw
exceptions. Note that this requires platform-specific runtime
support that does not exist everywhere. Moreover, it only allows
_trapping_ instructions to throw exceptions, i.e. memory
references or floating point instructions. It does not allow
exceptions to be thrown from arbitrary signal handlers such as
`SIGALRM'.
This means that exceptioning out from the middle of some random code is NEVER safe. You can only except out of SIGSEGV, SIGBUS, and SIGFPE, and only if you pass -fnon-call-exceptions and they were triggered due to a fault in the running code. The only reason this worked on thread 1 is because, due to the existence of the usleep() call, G++ was forced to assume that it might throw. With thread 2, G++ can see that no trapping instruction was present, and eliminate the try-catch block.
You may find the pthread cancellation support more akin to what you need, or otherwise just add a test like this somewhere:
if (*(volatile int *)terminate_flag) throw terminate_exception();
In Boost.thread a thread can be interrupted by invoking the interrupt() member function of the corresponding boost::thread object. It uses pthread condition variables to communicate with the thread and allows you to define interruption points in the thread code. I would avoid use of pthread_kill in C++. The fact that boost thread doesn't use pthread_kill anywhere in their code confirms this I think.