pcent
pcent

Reputation: 2049

Are there possible approaches to map signal handling (c library) into a c++ exception?

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

Answers (6)

Guillermo Calvo
Guillermo Calvo

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

Dummy00001
Dummy00001

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

mtvec
mtvec

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

Alex B
Alex B

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

avakar
avakar

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

Artyom
Artyom

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

Related Questions