Background
In my C++ program I have a SIGALRM handler in which I want to convert the signal into an exception by doing a throw (I understand that in general this is not good practice, but in the system I am working on it's probably the only option). My problem here is that SIGALRM handler could be invoked when we are doing a malloc, while throw will call __cxa_allocate_exception which does another malloc. The two malloc calls can hit a deadlock in glibc 2.12. I tried pre-allocating the exception, but the call to __cxa_allocate_exception still happened. I checked the source code of gcc and there doesn't seem to be any condition of putting the __cxa_allocate_exception call.
Additional Background
I install signal handler right before a try block and uninstall it after the catch. I'm throwing from the signal handler and this way I think it will be inside the try block (Let's not consider the case where the signal is received when we are in the catch logic) and can be caught correctly.
I think I'm hitting the malloc deadlock described here: https://sourceware.org/bugzilla/show_bug.cgi?id=13699 and here https://sourceware.org/ml/libc-alpha/2012-02/msg00272.html .
Question
My question is: is there anyway I can prevent throw from calling malloc? (Also, I understand that I can block the SIGALRM signal when I'm doing a malloc, but I'm afraid that there are too many places to block).
Thanks in advance. Any help/reference is high appreciated.
The general problem is that if your signal handler is called while in ANY async-unsafe library function (such as malloc or printf), jumping out of the signal handler (via longjmp or exception) will likely leave the glibc in an inconsistent state, which will crash or otherwise misbehave the next time you call anything.
So even if you were able to avoid the call to malloc in the exception setup, and throw the exception and catch and handle it, your program would stiil crash the next time it called malloc afterwards.
The only way to avoid this is to ensure that the signal handler cannot be called while in an async-unsafe library function. You can do that by using sigblock to block and unblock the signal around EVERY call to a signal-unsafe function ANYWHERE in your program:
oldmask = sigblock(SIGALRM);
...call to malloc or printf or whatever...
setsetmask(oldmask);
This is possible, but not terribly practical.
The manual states that malloc is "AS-Unsafe", which means it's not safe to call it inside asychronous signal handlers. If you do, your program has undefined behavior.
Related
I am facing a problem in my code which is as follows:
1.A process was using malloc to allocate the memory.
2.While allocation process was interrupted and respective signal handler was
called.
3.in the signal handler again malloc was called, which leads to a hang.
Now after some googling i came to know that i am not supposed to allocate memory in signal handler.
Is there a way to handle this problem which does not require me to avoid using malloc in signal handler? for e.g. checking if a malloc is already in progress or holds lock.
Inside of signal handler you can only call async-signal-safe functions. malloc is not one of them. You may try preallocating memory to be used in signal handler in advance (before installing signal handler) though.
I just stumbled upon the segvcatch library which promises to wrap segfaults and floating point errors into appropriate exceptions.
Is using this library safe, if I add the precondition that all segfaults caught will only be null pointer accesses (i.e., no array overflows or invalid pointers which could have screwed up the memory completely before segfaulting, resulting in undefined behaviour anyway)? Will the program still have defined semantics after catching a nullptr segfault? What about floating point errors? Do they behave better/different?
Sidenote: Please no comments stating that any program producing a segfault is ill-formed anyway and should be debugged/fixed. I know that and I agree. Still, I am interested in this question.
Not safe.
The signal handlers are very simple, and they are simply wrong. Here's the SEGV handler:
void default_segv()
{
throw std::runtime_error("Segmentation fault");
}
That is quite illegal, at least on POSIX. Throwing an exception from within a signal handler is a very, very bad idea.
Addendum
So why is this a bad idea?
With SIGALRM, it's worse than a bad idea; it's undefined behavior because alarms are asynchronous. With SIGSEGV and SIGBUS it's an extremely bad idea. With other signals, it's merely a bad idea. It might work, sometimes. Other times, it might not. Results can be quite disastrous when the magic doesn't work.
I'll look at SEGV first. One common cause of segmentation violations and bus errors is smashing the stack. There is no stack to unwind if this was the cause of the signal. The throw will try to unwind the stack, which will raise another SEGV. Now what? On my computer, that's a disaster.
Regardless of the signal, throwing inside a signal handler is not safe with respect to RAII because free() (and hence delete) is not safe to call within the context of a handler. There are a whole slew of functions that aren't safe to call from within the context of a signal handler. Everything that happens after the throw in the handler is done from within the context of the signal handler because the throw doesn't return from the handler. The throw bypasses the return.
Those unsafe calls and the unsafe unwinding means that a new signal can be raised while still handling that old signal. This recursive signal is highly problematic. On my computer, for example, the signal gets changed to SIGSTOP. The program doesn't exit, it doesn't drop core. It just hangs there, permanently frozen until I either kill -9 it or reboot the machine.
What's the difference between those three, and how shall I end program in case of exception which I can't handle properly?
abort indicates "abnormal" end to the program, and raises the the POSIX signal SIGABRT, which means that any handler that you have registered for that signal will be invoked, although the program will still terminate afterwords in either case. Usually you would use abort in a C program to exit from an unexpected error case where the error is likely to be a bug in the program, rather than something like bad input or a network failure. For example, you might abort if a data structure was found to have a NULL pointer in it when that should logically never happen.
exit indicates a "normal" end to the program, although this may still indicate a failure (but not a bug). In other words, you might exit with an error code if the user gave input that could not be parsed, or a file could not be read. An exit code of 0 indicates success. exit also optionally calls handlers before it ends the program. These are registered with the atexit and on_exit functions.
std::terminate is what is automatically called in a C++ program when there is an unhandled exception. This is essentially the C++ equivalent to abort, assuming that you are reporting all your exceptional errors by means of throwing exceptions. This calls a handler that is set by the std::set_terminate function, which by default simply calls abort.
In C++, you usually want to avoid calling abort or exit on error, since you're better off throwing an exception and letting code further up the call stack decide whether or not ending the program is appropriate. Whether or not you use exit for success is a matter of circumstance - whether or not it makes sense to end the program somewhere other than the return statement in main.
std::terminate should be considered a last-ditch error reporting tool, even in C++. The problem with std::terminate is that the terminate handler does not have access to the exception that went unhandled, so there's no way to tell what it was. You're usually much better off wrapping the entirety of main in a try { } catch (std::exception& ex) { } block. At least then you can report more information about exceptions that derived from std::exception (although of course exceptions that do not derive from std::exception would still end up unhandled).
Wrapping the body of main in try { } catch(...) { } isn't much better than setting a terminate handler, because again you have no access to the exception in question. There is at least one benefit, though: whether stack unwinding is done when an exception goes completely uncaught is implementation defined, so if you need guaranteed stack unwinding, this would be a way to get that.
std::abort and std::exit (and more: std::_Exit, std::quick_exit) are just lower level functions. You use them to tell the program what you want it to do exactly: what destructors (and if) to call, what other clean-up functions to call, what value to return, etc.
std::terminate is a higher level abstraction: it is called (by either run-time or you) to indicate that an error in the program occurred and that for some reason it is not possible to handle by throwing an exception. The necessity for that typically occurs when error occurs in the exception mechanism itself, but you can use it any time when you do not want your program to continue beyond the given error. I compiled the full list of situations when std::terminate is called in my post. It is not specified what std::terminate does, because you are in control of it. You can configure the behavior by registering any functions. The limitations you have are that the function cannot return back to the error site and it cannot exit via an exception, but technically you can even start your message pump inside. For the list of useful things that you can do inside, see my other post.
In particular, note that std::terminate is considered an exception handler in contexts where std::terminate is called due to a thrown exception that could not be handled, and you can check what the exception was and inspect it by using C++11 using std::rethrow_exception and std::current_exception. It is all in my post.
quick_exit() !
If your program is multi-threaded, then calling exit() will most likely result in a crash because global/static std::thread objects will be attempted to destruct without exiting their threads.
If you want to return an error code and exit the program (more or less) normally, call quick_exit() in multi-threaded programs.
For abnormal termination (without a possibility for you to specify the error code), abort() or std::terminate() can be called.
Note: quick_exit() has not been supported by MSVC++ until version 2015 .
terminate() is automatically called
when an exception occurs that cannot
be handled. By default, terminate()
calls abort(). You can set a custom
handle with set_terminate() function.
abort() sends the SIGABRT signal.
exit() is not necessarily a bad
thing. It successfully exits the
application, and calls atexit()
functions in LIFO order. I don't
normally see this in C++
applications, however, I do see it in
many unix based applications where it
sends an exit code at the end.
Usually a exit(0) indicates a
successful run of the application.
terminate leaves you the possibility to register what will happen when it is called. Should be one of the other two.
exit is a normal exit allowing to specify an exit status. Handlers registered by at_exit() are run
abort is an abnormal exit. The only thing which is ran is the signal handler for SIGABRT.
My advice would be not to use any of them. Instead, catch the exceptions you can't handle in main() and simply return from there. This means that you are guaranteed that stack unwinding happens correctly and all destructors are called. In other words:
int main() {
try {
// your stuff
}
catch( ... ) {
return 1; // or whatever
}
}
I have a Windows C++ console program, and if I don't call ReleaseDriver() at the end of my program, some pieces of hardware enter a bad state and can't be used again without rebooting.
I'd like to make sure ReleaseDriver() gets runs even if the program exits abnormally, for example if I hit Ctrl+C or close the console window.
I can use signal() to create a signal handler for SIGINT. This works fine, although as the program ends it pops up an annoying error "An unhandled Win32 exception occurred...".
I don't know how to handle the case of the console window being closed, and (more importantly) I don't know how to handle exceptions caused by bad memory accesses etc.
Thanks for any help!
Under Windows, you can create an unhandled exception filter by calling SetUnhandledExceptionFilter(). Once done, any time an exception is generated that is not handled somewhere in your application, your handler will be called.
Your handler can be used to release resources, generate dump files (see MiniDumpWriteDump), or whatever you need to make sure gets done.
Note that there are many 'gotchas' surrounding how you write your exception handler function. In particular:
You cannot call any CRT function, such as new
You cannot perform any stack-based allocation
If you do anything in your handler which causes an exception, Windows will immediately terminate your application by ripping the bones out of its back. You get no further chances to shut down gracefully.
You can call many Windows API functions. But you can't sprintf, new, delete... In short, if it isn't a WINAPI function, it probably isn't safe.
Because of all of the above, it is advisable to make all the variables in your handler function static variables. You won't be able to use sprintf, so you will have to format strings ahead of time, during initialization. Just remember that the machine is in a very unstable state when your handler is called.
If I'm not mistaken, you can detect if the console is closed or the program is terminated with Ctrl+C with SetConsoleCtrlHandler:
#include <windows.h>
BOOL CtrlHandler(DWORD)
{
MessageBox(NULL, "Program closed", "Message", MB_ICONEXCLAMATION | MB_OK);
exit(0);
}
int main()
{
SetConsoleCtrlHandler((PHANDLER_ROUTINE)&CtrlHandler, TRUE);
while (true);
}
If you are worried about exceptions, like bad_alloc, you can wrap main into a try block. Catch std::exception& which should ideally be the base class of all thrown exception, but you can also catch any C++ exception with catch (...). With those exceptions, though, not all is lost, and you should figure out what is being thrown and why.
Avoiding undefined behavior also helps. :)
You can't (guarantee code runs). You could lose power, then nothing will run. The L1 instruction cache of your CPU could get fried, then your code will fail in random ways.
The most sure way of running cleanup code is in a separate process that watches for exit of the first (just WaitForSingleObject on the process handle). A separate watchdog process is as close as you can get to a guarantee (but someone could still TerminateProcess your watchdog).
The C++ standard provides the std::set_terminate function which lets you specify what function std::terminate should actually call. std::terminate should only get called in dire circumstances, and sure enough the situations the standard describes for when it's called are dire (e.g. an uncaught exception). When std::terminate does get called the situation seems analagous to being out of memory -- there's not really much you can sensibly do.
I've read that it can be used to make sure resources are freed -- but for the majority of resources this should be handled automatically by the OS when the process exits (e.g. file handles). Theoretically I can see a case for if say, you needed to send a server a specific message when exiting due to a crash. But the majority of the time the OS handling should be sufficient.
When is using a terminate handler the Right Thing(TM)?
Update: People interested in what can be done with custom terminate handlers might find this non-portable trick useful.
This is just optimistic:
but for the majority of resources this should be handled automatically by the OS when the process exits
About the only resources that the OS handles automatically are "File Handles" and "Memory" (And this may vary across OS's).
Practically all other resources (and if somebody has a list of resources that are automatically handled by OS's I
would love that) need to be manually released by the OS.
Your best bet is to avoid exit using terminate() and try a controlled shut down by forcing the stack to unwind correctly.
This will make sure that all destructors are called correctly and your resources are released (via destructors).
About the only thing I would do is log the problem. So that when it does happened I could go back and fix the code so that it does not happen again. I like my code to unwind the stack nicely for resource deallocation, but this is an opinion some people like abrupt halts when things go badly.
My list of when terminate is called:
In general it is called when the exception handling mechanism cannot find a handler for a thrown exception. Some specific examples are:
An exception escapes main()
Note: It is implementation defined whether the stack is unwound here.
Thus I always catch in main and then rethrow (if I do not explicitly handle).
That way I guarantee unwinding of the stack (across all platforms) and still get the benefits of the OS exception handling mechanism.
Two exceptions propagating simultaneously.
An exception escapes a desatructor while another exception is propagating.
The expression being thrown generates an exception
An exception before or after main.
If an exception escapes the constructor/destructor of a global object.
If an exception escapes the destructor of a function static variable.
(ie be careful with constructors/destructors of nonlocal static object)
An exception escapes a function registered with atexit().
A rethrow when no exception is currently propagating.
An unlisted exception escapes a method/function that has exception specifier list.
via unexpected.
Similar to a statement made in Martin York's answer, about the only thing I do in a custom terminate handler is log the problem so I can identify and correct the offending code. This is the only instance I find that using a custom terminate handler is the Right Thing.
Since it is implementation-defined whether or not the stack is unwound before std::terminate() is called, I sometimes add code to generate a backtrace in order to locate an uncaught exception1.
1) This seems to work for me when using GCC on Linux platforms.
I think the right question would be how to avoid the calls to terminate handler, rather than when to use it.