I once wrote a C++ class that convert OS signals to exceptions. The
problem is what to do when you catch the signal, as Alf said, when you
encounter a bug you should fix it. But if you have a program that does
large iterations and kind of clean itself between iterations it might
be helpfull:
#ifndef SIG_EXCEPT_H
#define SIG_EXCEPT_H
/*******************************************************************************
File name : sigexception.h
Programmer : Yuval Lifshitz
Date : 03-sep-2003
Description : Try/Catch mechanism for OS signals.
Usage example:
TRY {
// write code here
}
CATCH {
// write code here
ex.WriteMsg();
cout << "signal number = " << ex.getSignal() << endl;
}
Notes: (1) This mechanism is NOT thread safe.
(2) The CATCH macro must follow immediatly after the
closing brackets of the TRY macro
(3) inside the CATCH block there exists a local variable
named ex holding the thrown signal data.
Change log : 23-sep-2004 make gcc compatible
add thread index hashing
*******************************************************************************/
// include files
#include <stack>
#include <iostream>
#include <pthread.h>
#include <signal.h>
#include <setjmp.h>
// signal description list - used at the psignal function
extern const char *const sys_siglist[];
// jump function type
extern "C" {
typedef void (*jump_func_t)(int);
}
// main class definition
class TryCatchAsync
{
public:
// const and enum
enum {MAX_THREAD_NUM = 100};
//---------------------------
// internal class/type definitions
//---------------------------
//---------------------------------------------------------------
// Class Name : sigjmp_container
// Description : Container to encapsulate the sigjmp_buf type.
// This is done for the conviniece of allocation,
// since the original type is an array of integers.
//----------------------------------------------------------------
class sigjmp_container {
private:
sigjmp_buf m_sigbuf;
public:
sigjmp_container() {}
~sigjmp_container() {}
operator sigjmp_buf * ()
{
return &m_sigbuf;
}
sigjmp_buf * get_buf()
{
return &m_sigbuf;
}
};
//-----------------------------------------------
// Class Name : Exception
// Description : The exception thrown by the try
//-----------------------------------------------
class Exception {
public:
Exception(int sig) : m_sig(sig) {}
int getSignal() const
{
return m_sig;
}
void WriteMsg() const
{
psignal(m_sig, "signal thrown");
}
private:
int m_sig;
};
// jump adresses stack type
typedef std::stack<sigjmp_container> jump_stack_t;
// the constructor is used to generate the array of jump functions
// the object should be instanciated only once - but has no effect
// if instanciated more then once, since the relevant execution
// is done in compile time
// constructor
TryCatchAsync();
// destructor
~TryCatchAsync() {}
// static member functions
static void SigMaskAdd(int sig);
static void Push(sigjmp_container &curr_addr);
static void Throw();
static int GetThreadIndex();
// member functions
template <int func_id>
static void Jump(int sig)
{
pthread_t pt = GetThreadIndex();
m_sig[pt] = sig;
siglongjmp(*(sigjmp_buf *)m_addr[pt].top().get_buf(), 1);
}
private:
// data members
static int m_sig[MAX_THREAD_NUM];
static jump_stack_t m_addr[MAX_THREAD_NUM];
static jump_func_t m_jump_func[MAX_THREAD_NUM];
};
//-----------------------------------------------
// Class Name : JUMP_FUNC_GENERATOR
// Description : a template struct that instanciate
// an array of different "Jump" functions.
// Note: this is done in a "generative programming"
// method in compile time.
//-----------------------------------------------
template <int N>
struct JUMP_FUNC_GENERATOR
{
JUMP_FUNC_GENERATOR(jump_func_t *jump_func_arr)
{
jump_func_arr[N-1] = TryCatchAsync::Jump<N-1>;
JUMP_FUNC_GENERATOR<N-1> tmp_creator(jump_func_arr);
tmp_creator = tmp_creator; // to avoid "unusead variable" warning
}
};
// termination condition for the generative process
template <>
struct JUMP_FUNC_GENERATOR<0>
{
JUMP_FUNC_GENERATOR(jump_func_t *jump_func_arr)
{
jump_func_arr[0] = TryCatchAsync::Jump<0>;
}
};
//------------------
// macro definitions
//------------------
#define SIG_INIT \
TryCatchAsync::SigMaskAdd(SIGFPE); \
TryCatchAsync::SigMaskAdd(SIGSEGV); \
TryCatchAsync::SigMaskAdd(SIGILL); \
TryCatchAsync::SigMaskAdd(SIGBUS);
// note: new signals should be added in the SIG_INIT macro
#define TRY SIG_INIT try { TryCatchAsync::sigjmp_container curr_addr;\
if (sigsetjmp(*(sigjmp_buf *)curr_addr, 1) == 0) { \
TryCatchAsync:
ush(curr_addr); \
} \
else { \
TryCatchAsync::Throw(); \
}
#define CATCH } catch(TryCatchAsync::Exception &ex)
#endif // RSEXCEPT_H