Tuesday, July 8, 2008

C++ convert signals into exceptions

Here is a technique to convert signals into exceptions:


#include "signal.h"

template class SignalTranslator
{
private:
class SingleTonTranslator
{
public:
SingleTonTranslator()
{
signal(SignalExceptionClass::GetSignalNumber(), SignalHandler);
}

static void SignalHandler(int)
{
std::cout << "Signal handled and logged" << std::endl;
throw SignalExceptionClass();
}
};

public:
SignalTranslator()
{
static SingleTonTranslator s_objTranslator;
}
};


class SegmentationFault : public std::exception
{
public:
virtual const char* what() const throw() {
return "Segmentation Fault";
}
static int GetSignalNumber() {return SIGSEGV;}
};


I put the above in a SignalHandler.hpp. Then when I want to use it I include that file and instantiate the handlers that I want


// Set up signal handleing for Seg Fault. When SegFault occurs it will throw a exception
SignalTranslator g_objSegmentationFaultTranslator;


To test this code you can simply raise that exception ( raise(SIGSEGV); )

1 comment:

Kurt Guntheroth said...

The original program doesn't even compile, and it's way complicated.

On g++ 4.4, you need to set -fnon-call-exceptions in addition.

# include
# include // linux signals and signal handling actions
# include
# include
# include
# include

static void HandleSEGV( int /*sig*/ )
{
fprintf(stderr, "in segv handler\n");
throw (int)1;
}// end trapWorkerInterfaceSignal

int main(int, char** argv)
{
// set up signal handler for SIGINT (^C interrupt) once per process
struct sigaction sa;
sigaction(SIGSEGV, 0, &sa); // reads existing handler, iniz's sa
assert(sa.sa_handler == SIG_DFL);
assert(sa.sa_flags == 0);
sa.sa_handler = HandleSEGV;// set our handler
if (sigaction(SIGSEGV, &sa, 0))
{
fprintf(stderr, "%s: Abnormal exit. Could not set signal handler. errno %d\n", argv[0], errno);
return (1);
}

char* p = 0;

try
{
*p = 1;
throw (int)2;
fprintf(stderr, "%s: after segv\n", argv[0]);
}
catch (int i)
{
fprintf(stderr, "%s: caught int %d\n", argv[0], i);
}
return 0;
}