How to Handle SIGABRT signal? - c++

Here is the code on which I set my handler for SIGABRT signal then I call abort() but handler does not get trigered, instead program gets aborted, why?
#include <iostream>
#include <csignal>
using namespace std;
void Triger(int x)
{
cout << "Function triger" << endl;
}
int main()
{
signal(SIGABRT, Triger);
abort();
cin.ignore();
return 0;
}
PROGRAM OUTPUT:

As others have said, you cannot have abort() return and allow execution to continue normally. What you can do however is protect a piece of code that might call abort by a structure akin to a try catch. Execution of the code will be aborted but the rest of the program can continue. Here is a demo:
#include <csetjmp>
#include <csignal>
#include <cstdlib>
#include <iostream>
jmp_buf env;
void on_sigabrt (int signum)
{
signal (signum, SIG_DFL);
longjmp (env, 1);
}
void try_and_catch_abort (void (*func)(void))
{
if (setjmp (env) == 0) {
signal(SIGABRT, &on_sigabrt);
(*func)();
signal (SIGABRT, SIG_DFL);
}
else {
std::cout << "aborted\n";
}
}
void do_stuff_aborted ()
{
std::cout << "step 1\n";
abort();
std::cout << "step 2\n";
}
void do_stuff ()
{
std::cout << "step 1\n";
std::cout << "step 2\n";
}
int main()
{
try_and_catch_abort (&do_stuff_aborted);
try_and_catch_abort (&do_stuff);
}

Although you can replace handler for SIGABRT and abort() will pay attention to the handler, the abort is only inhibited if the signal handler does not return. The relevant quote in C99 is in 7.20.4.1 paragraph 2:
The abort function causes abnormal program termination to occur, unless the signal SIGABRT is being caught and the signal handler does not return. ...
Your signal handler does return and thus the program is aborted.

You get those symptoms i.e. the popup debug dialog, when you have a debug build (with windows and Visual Studio- I'm testing with 2012 version), since it sets a debug break, in the debug implementation of abort() ).
If you pick "ignore" you get that message "Function triger"
If you do a release build, then you don't get the debug popup dialog, and you get the message, as expected

Related

cannot catch segmentation fault second time

I'm trying to restart the program when segmention fault occures.
I have following minimal reproducible code:-
#include <csignal>
#include <unistd.h>
#include <iostream>
int app();
void ouch(int sig) {
std::cout << "got signal " << sig << std::endl;
exit(app());
}
struct L { int l; };
static int i = 0;
int app() {
L *l= nullptr;
while(1) {
std::cout << ++i << std::endl;
sleep(1);
std::cout << l->l << std::endl; //crash
std::cout << "Ok" << std::endl;
}
}
int main() {
struct sigaction act;
act.sa_handler = ouch;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGKILL, &act, 0);
sigaction(SIGSEGV, &act, 0);
return app();
}
It successfully catches sigsegv first time but after it prints 2, it shows me segmentation fault (core dumped)
1
got signal 11
2
zsh: segmentation fault (core dumped) ./a.out
tested with clang 12.0.1 and gcc 11.1.0 on ArchLinux
Is this operating system specific behavior or is something wrong in my code
The problem is that when you restart the program by calling exit(app()) from inside ouch(), you are still technically inside the signal handler. The signal handler is blocked until you return from it. Since you never return, you therefore cannot catch a second SIGSEGV.
If you got a SIGSEGV, then something really bad has happened, and there is no guarantee that you can just "restart" the process by calling app() again.
The best solution to handle this is to have another program start your program, and restart it if it crashed. See this ServerFault question for some suggestions of how to handle this.

Invoking raise(signal) terminates c++ program

I have two program running on my Raspberry Pi. One interfaces with a user, the other listens for messages and updates a message file when directed. I want the other to signal to the first that the messages have been updated so the first can reload the message file. I though a SIGUSR1 signal would do what I need. However, when I raise the signal, it terminates my program, which still needs to continue listening for new messages. I therefore constructed the test case program "test_raise.cpp":
#include <iostream>
#include <csignal>
int main(){
std::cout << "Ready to raise SIGUSR1." << std::endl;
std::raise(SIGUSR1);
std::cout << "SIGUSR1 has been raised." << std::endl;
}
I am using this compiler:
gcc version 6.3.0 20170516 (Raspbian 6.3.0-18+rpi1+deb9u1)
which generates the following output
pi#raspberrypi:~$./test_raise
Ready to raise SIGUSR1.
User defined signal 1
pi#raspberrypi:~$
Note that the 2nd text output is not produced. None of the documentation I have looked at indicates that raise terminates the issuing program. (Have I missed something?)
Is this a normal function of raise? Is there a way to do signals without terminating the program? What is my better alternative?
Thanks...
Based on a response, I have a program (invoked prior to the raise program) which has a handler for the USR1 signal:
#include <iostream>
#include <csignal>
#include <unistd.h>
bool flag;
void signalHandler( int signum ) {
std::cout << "Interrupt signal (" << signum
<< ") received." << std::endl;
flag = true;
exit(signum);
}
int main () {
signal(SIGUSR1, signalHandler);
flag = false;
while(1) {
std::cout << "Sleeping...." << std::endl;
if (flag){
std::cout << "SIGUSR1 reception noted by main. "
<< std::endl;
flag = false;
}
sleep(1000*1000); // sleep 1 second
}
return 0;
}
Now there is a handler, but the messages was never received and the raise program still terminates prior to the final message. What am I missing here?
If you haven't installed a signal handler to catch and deal with SIGUSR1 then the default behaviour is to terminate the process.
If you intend to handle the signal, then install an appropriate signal handler and do what you need to do to handle the signal. (Remember that there are very few things you are allowed to do in a signal handler).

`signal` function on CentOS: unexpected behavior

I need to disable SIGPIPE on CentOS application, because this signal crashes my application when it works with unstable Internet connection.
I use following code in main function:
signal(SIGPIPE, SIG_IGN);
However, program still crashes with SIGPIPE. What is the reason? Have I to call this function on each thread, or it is enough to call in main function, and program will ignore SIGPIPE globally? And if it is not required to be called on each thread, why SIGPIPE still crashes program if it is supposed to ignore the signal?
Here it is a code sample that let you set up your own signal handler on linux, catch SIGPIPE and do something with that.
#include <signal.h>
#include <unistd.h>
#include <cerrno>
#include <system_error>
#include <iostream>
static sigset_t theMask;
static int count = 0;
static void
signalWrapper(
int theSignalNumber,
siginfo_t* theSignalDescription,
void* theUserContext)
{
// Do something here as reaction to you SIGPIPE
// This is better way to react on such things
std::cout << "Got signal " << theSignalNumber << std::endl;
// Reinstall handler
struct ::sigaction sa;
sa.sa_sigaction = &signalWrapper;
sa.sa_mask = theMask;
sa.sa_flags = SA_SIGINFO;
try
{
if (::sigaction(theSignalNumber, &sa, NULL) == -1)
throw std::error_code(errno, std::system_category());
}
catch (const std::error_code& ec)
{
std::cerr << ec << std::endl;
}
count++;
}
void
setupSignalHandlers()
{
struct ::sigaction sa;
// Prepare mask
sigemptyset(&theMask);
sigaddset(&theMask, SIGPIPE);
// Add some more if you need it to process
sa.sa_mask = theMask;
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &signalWrapper;
// Perform setup
try
{
if (::sigaction(SIGPIPE, &sa, NULL) == -1)
throw std::error_code(errno, std::system_category());
}
catch (const std::error_code& ec)
{
std::cerr << ec << std::endl;
}
}
int
main()
{
std::cout << "Set handler!" << std::endl;
setupSignalHandlers();
std::cout << "Emit 5 SIGPIPE signals" << std::endl;
while (count < 5)
{
kill(getpid(), SIGPIPE);
usleep(100);
}
return 0;
}
and output:
Set handler!
Emit 5 SIGPIPE signals
Got signal 13
Got signal 13
Got signal 13
Got signal 13
Got signal 13
I provide signal handler since it is more correct to process signal that breaks your application than ignore it. Perhaps you need to reestablish connection or do some other stuff.
According to the man page for Signal(2), "The Effects of signal() in a multithreaded process are unspecified." You might try making sure to call signal() in the main thread before creating any other threads, but it's not guaranteed to work.
In any case signal() is deprecated, so I would suggest switching to sigaction(). I use it in multithreaded applications all the time without any problems.

Cleanup code in Win32 console program

This question is based on the following question: Handle CTRL+C on Win32
I'm working on a multithread server, running on Linux and Windows. I can't use boost or other frameworks, only std c++.
I have a problem with the cleanup code on the win32 side. The linux side is working fine: when I want to shutdown the server, I send SIGINT (with CTRL+C), the signal handler sets a global variable and the main pthread executes the cleanup instructions (joining other pthreads, freeing heap memory, etc.).
On windows it looks not so simple to get the same behavior.
I have written a simple test program to understand how the signal handlers works in windows.
#include <iostream>
#include <windows.h>
bool running;
BOOL WINAPI consoleHandler(DWORD signal) {
if (signal == CTRL_C_EVENT) {
running = false;
std::cout << "[CTRL+C]\n";
return TRUE;
}
return FALSE;
}
int main(int argc, char **argv) {
running = true;
if (!SetConsoleCtrlHandler(consoleHandler, TRUE)) {
std::cerr << "Error: " << GetLastError() << '\n';
return -1;
}
std::cout << "Main thread working hard...\n";
while (running) { ; }
for (int i = 0; i < 20; i++)
std::cout << "This is the " << i << "th fake cleanup instruction\n";
return 0;
}
The output is the following:
$ test.exe
Main thread working hard...
[CTRL+C]
This is the 0th fake cleanup instruction
This is the 1th fake cleanup instruction
So the main thread is killed quickly, only after two instruction. In the previous question one of the suggestion was to move the cleanup code in the handler, but is not really helping:
suppose that the handler function looks like this:
BOOL WINAPI consoleHandler(DWORD signal) {
if (signal == CTRL_C_EVENT) {
running = false;
std::cout << "[CTRL+C]\n";
for (int i = 0; i < 20; i++)
std::cout << "This is the " << i << "th fake cleanup instruction\n";
return TRUE;
}
return FALSE;
}
Now the behavior is even worse! The output is:
$ test.exe
Main thread working hard...
[CTRL+C]
This is the
According to MSDN, it seems that the process is always killed:
A HandlerRoutine can perform any necessary cleanup, then take one of
the following actions:
Call the ExitProcess function to terminate the process.
Return FALSE. If none of the registered handler functions returns TRUE, the default handler terminates the process.
Return TRUE. In this case, no other handler functions are called and the system terminates
the process.
Am I missing something obvious?
What's the proper way to terminate a win32 console process and executes its cleanup code?
This is one way to do it, though I would suggest you use an event HANDLE and WaitForSingleObject, as it would tend to be considerably more "yielding". I left the high velocity spin-loop in this just for you to peg one of your cores while still seeing the handler is intercepted.
I took the liberty of modifying your running state to be atomically evaluated and set respectively, as I didn't want the optimizer throwing out the eval in the main loop.
#include <iostream>
#include <cstdlib>
#include <windows.h>
// using an event for monitoring
LONG running = 1;
BOOL WINAPI consoleHandler(DWORD signal)
{
if (signal == CTRL_C_EVENT)
{
std::out << "Received Ctrl-C; shutting down..." << std::endl;
InterlockedExchange(&running, 0);
return TRUE;
}
return FALSE;
}
int main(int argc, char **argv)
{
if (!SetConsoleCtrlHandler(consoleHandler, TRUE))
{
std::cerr << "Error: " << GetLastError() << '\n';
return EXIT_FAILURE;
}
std::cout << "Main thread working hard...\n";
while (InterlockedCompareExchange(&running, 0, 0) == 1);
std::cout << "Graceful shutdown received. Shutting down now." << std::endl;
return 0;
}
Output (note: I pressed ctrl-C, in case it wasn't obvious)
Main thread working hard...
Received Ctrl-C; shutting down...
Graceful shutdown received. Shutting down now.
Note: I tested this in debug and release in both 64 and 32 bit processes, no issues. And you can run it from the VS debugger. Just select "Continue" when informed you can continue if you have a handler installed, which you do.
On Windows you can use a signal handler as well:
static void shutdown(int signum)
{
printf("got signal #%d, terminating\n", signum);
// cleanup
_exit(1);
}
signal(SIGINT, shutdown);
signal(SIGTERM, shutdown);
signal(SIGSEGV, shutdown);
Ctrl-C is mapped to SIGINT just like on Linux.
This won't handle the user closing the console window using mouse, however.

How to exit program execution in C++?

Which function is used in C++ stdlib to exit from program execution with status code?
In Java, there's:
System.exit(0)
Assuming you only have one thread:
#include <iostream>
int main()
{
std::cout << "Hello, World!\n";
return(0);
// PROGRAM ENDS HERE.
std::cout << "You should not see this.\n";
return(0);
}
Output:
Hello, World!
The return(0); can be placed anywhere you like - it'll end int main(), and hence your program.
Alternatively, you can call exit(EXIT_SUCCESS); or exit(EXIT_FAILURE); from anywhere you like:
/* exit example */
#include <stdio.h>
#include <stdlib.h>
int main ()
{
FILE * pFile;
pFile = fopen("myfile.txt", "r");
if(pFile == NULL)
{
printf("Error opening file");
exit (1);
}
else
{
/* file operations here */
}
return 0;
}
In addition to the other responses you can also invoke abort, terminate, quick_exit (exits without calling destructors, deallocating etc; hence the name)
terminate calls abort by default but can call any terminate handler you set.
Example usage of abort and set_terminate (to se the handler used by terminate), quick_exit can be called (see example #2)
// set_terminate example
#include <iostream> // std::cerr
#include <exception> // std::set_terminate
#include <cstdlib> // std::abort
void myterminate () {
std::cerr << "terminate handler called\n";
abort(); // forces abnormal termination
}
int main (void) {
std::set_terminate (myterminate);
throw 0; // unhandled exception: calls terminate handler
return 0;
}
quick_exit/at_quick_exit example:
/* at_quick_exit example */
#include <stdio.h> /* puts */
#include <stdlib.h> /* at_quick_exit, quick_exit, EXIT_SUCCESS */
void fnQExit (void)
{
puts ("Quick exit function.");
}
int main ()
{
at_quick_exit (fnQExit);
puts ("Main function: Beginning");
quick_exit (EXIT_SUCCESS);
puts ("Main function: End"); // never executed
return 0;
}
I'm not entirely certain why one would call quick_exit but it exists and thus I should provide documentation for it (courtesy of http://www.cplusplus.com/reference )
Additionally one can call at_exit as the equivalent of at_quick_exit.
Admittedly I am not all that familiar with set_terminate and terminate as I don't call them myself, but I would guess you could use quick_exit as a terminate handler if you wanted; or a custom one (but please don't quote me on that).
In C++, you can use exit(0)
for example:
switch(option){
case 1:
//statement
break;
case 2:
//statement
exit(0);