Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /// ----------------------- seh.h ------------------------------------------
- #include <iostream>
- #include <signal.h>
- #include <setjmp.h>
- #include <cstdio>
- #include <string.h>
- ///begin of SEH try section - use similar to try-catch
- #define __seh_try for (LinuxSEH __sehContext;__sehContext.enter();) if (__sehContext.catchRes(sigsetjmp(__sehContext,1)))
- ///begin of SEH except section.
- /**
- * @param x specify variable name (int) which receives signal number
- */
- #define __seh_except(x) else if (int x = __sehContext.except())
- ///Helper object to handle SEH under Linux
- /** It is always accessible as __sehContext inside try-except block */
- class LinuxSEH {
- public:
- ///constructor - prepares context
- LinuxSEH();
- ///destructor - performs cleanup
- ~LinuxSEH();
- ///called inside macro __seh_try
- /** causes, that for cycle will be executed once */
- inline bool enter() {return swp = !swp;}
- ///allows to convert context to jmp_buf to inicialize setjmp
- operator __jmp_buf_tag *() { return jmpbuf;}
- ///catches signal number after handler is executed. It is part of __seh_try macro
- /**
- * @param val value returned by setjmp. After handler is executed, it returns signal number
- */
- inline bool catchRes(int val) {return (signum = val) == 0;}
- ///used to implement __seh_except. Performs cleanup object's internal state and returns signal number
- int except();
- ///signal handler
- static void signalHandler(int sig);
- ///initializes LinuxSEH signal actions - SIGSEGV, SIGBUS and SIGILL
- static void init();
- ///initializes LinuxSEH to catch specified signal
- /**
- * @param signum signal number to catch using SEH
- */
- static void initSignal(int signum);
- protected:
- jmp_buf jmpbuf;
- __jmp_buf_tag *prevjmpbuf;
- mutable bool swp;
- int signum;
- static const struct sigaction standardSigAction;
- };
- /// ----------------------- seh.cpp ------------------------------------------
- static __thread __jmp_buf_tag *globjmpbuf = 0;
- void LinuxSEH::signalHandler(int sig) {
- if (globjmpbuf) {
- siglongjmp(globjmpbuf ,sig);
- }
- char buff[256];
- sprintf(buff,"Unhandled signal %d\n",sig);
- write(2,buff,strlen(buff));
- signal(sig,SIG_DFL);
- }
- LinuxSEH::LinuxSEH():swp(false) {
- prevjmpbuf = globjmpbuf;
- globjmpbuf = jmpbuf;
- }
- LinuxSEH::~LinuxSEH() {
- if (globjmpbuf == jmpbuf) globjmpbuf = prevjmpbuf;
- }
- int LinuxSEH::except() {
- if (globjmpbuf == jmpbuf) globjmpbuf = prevjmpbuf;
- return signum;
- }
- static struct sigaction initSigAction() {
- struct sigaction sig;
- sig.sa_handler = &LinuxSEH::signalHandler;
- sig.sa_flags = 0;
- sig.sa_restorer = 0;
- sigemptyset(&sig.sa_mask);
- return sig;
- }
- const struct sigaction LinuxSEH::standardSigAction = initSigAction();
- void LinuxSEH::init() {
- initSignal(SIGSEGV);
- initSignal(SIGBUS);
- initSignal(SIGILL);
- }
- void LinuxSEH::initSignal(int signum) {
- sigaction(signum,&standardSigAction,0);
- }
- /// ----------------------- example.cpp ------------------------------------------
- int main() {
- LinuxSEH::init();
- char *err = 0;
- __seh_try {
- __seh_try {
- *err = 'A';
- } __seh_except(signum) {
- std::cout << "signal: " << signum << " handled A" << std::endl;
- *err = 'B';
- }
- } __seh_except(signum) {
- std::cout << "signal: " << signum << " handled B" << std::endl;
- }
- LinuxSEH::initSignal(SIGTERM);
- __seh_try {
- std::cout << "terminate process please" << std::endl;
- sleep(10);
- } __seh_except(signum) {
- std::cout << "signal: " << signum << " handled C" << std::endl;
- }
- std::cout << "terminate process please" << std::endl;
- sleep(10);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement