Reputation: 2049
I have a c++ application linked against some c libraries.
Are there possible approaches to encapsulate the signal handling in a C++ class, so it could be handled as a c++ exception?
Upvotes: 1
Views: 598
Reputation: 797
I might have a solution for you.
I am developing exception4c, an exception handling framework for C. It can turn system signals into exceptions. For example, it lets you catch SIGSEGV
this way:
int * pointer = NULL;
try{
int oops = *pointer;
}catch(BadPointerException){
printf("No problem ;-)");
}
These exceptions are not C++ exceptions, though. The library is standard ANSI C (C89).
Upvotes: 0
Reputation: 17430
It sounds like you try to do something terribly wrong. Generally, do not do signals unless there is a special reason for it. Signal are there more for admin than for software developers.
Otherwise, it is quite complicated (and generally impossible) to map signals to exceptions, as OS is allowed to merge some signal. E.g. SIGCHLD would happen only once if two child processes had terminated simultaneously. And you can't schedule to throw two exceptions - one after another.
Another point would be that signal is allowed to be delivered to any thread in multi-threaded application. One thing is throwing exception. But you might run eventually into the problem of actually catching the exception precisely where you want it.
Beyond standard clean-up on termination and reaping the children - do not toy with signals. Modern *NIX allow to do pretty much everything application needs without signals.
Upvotes: 0
Reputation: 18326
As pointed out several times, doing this is general not a good idea. If you really want to do this, here is something I wrote a little while ago.
#include <signal.h>
#include <exception>
#include <iostream>
//template class that translates a signal in an exception
//the given SignalExceptionClass should have a static int signalNumber()
template<class SignalExceptionClass>
class SignalTranslator
{
private:
class SingletonTranslator
{
public:
SingletonTranslator()
{
signal(SignalExceptionClass::signalNumber(), handler);
}
static void handler(int)
{
throw SignalExceptionClass();
}
};
public:
//sigleton pattern so we don't install more than one handler
//for a given signal
SignalTranslator()
{
static SingletonTranslator translator;
}
};
//example for SIGFPE
class FloatingPointException : public std::exception
{
public:
static int signalNumber() {return SIGFPE;}
const char* what() const throw() {return "Floating point exception";}
};
//install translators
static SignalTranslator<FloatingPointException> fpeTranslator;
int main()
{
try
{
std::cout << "causing SIGFPE\n";
std::cout << 1 / 0 << std::endl;
}
catch (std::exception& e)
{
std::cout << e.what() << std::endl;
}
std::cout << "after SIGFPE\n";
}
In this example, every time a SIGFPE
is raised, a FloatingPointException
will be thrown. Running the example will output the following:
causing SIGFPE
Floating point exception
after SIGFPE
Note: this will not work for all types of signals. For example, it does not work for SIGSEGV.
Upvotes: 1
Reputation: 84962
If you mean if want throw an exception at an arbitrary point of code when the signal is delivered to the process, you can't. The signal is delivered in a different execution context, so your original thread won't catch it.
Even if you could, you shouldn't, as any assumptions about atomicity of your operations and exception safety guarantees would go out of the window.
Upvotes: 1
Reputation: 32685
You can't and if you could a lot of things would break.
What you should do is set a flag in the signal handler, periodically check in your code and throw an exception when you detect the flag is set.
Such an approach is similar to how threads get interrupted in Boost.Threads, which I strongly suggest you study.
Upvotes: 2
Reputation: 31271
Signal handling is something very tighten on the OS level, it is generally do not used for "error" handling unless they are SIGSEGV or SIGFPU that usually result that very bad things happened to program, but rather used to alarm on specific events that happened in system.
Also in signal handler you can perform very limited tasks, only few system calls are actually signal safe.
So, generally don't throw as a result of signal ;-)
Upvotes: 1