Advertisement
novacisko

SEH v Linuxu

Sep 4th, 2012
432
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.57 KB | None | 0 0
  1.  
  2. /// ----------------------- seh.h ------------------------------------------
  3. #include <iostream>
  4. #include <signal.h>
  5. #include <setjmp.h>
  6. #include <cstdio>
  7. #include <string.h>
  8.  
  9. ///begin of SEH try section - use similar to try-catch
  10. #define __seh_try for (LinuxSEH __sehContext;__sehContext.enter();) if (__sehContext.catchRes(sigsetjmp(__sehContext,1)))
  11. ///begin of SEH except section.
  12. /**
  13.  * @param x specify variable name (int) which receives signal number
  14.  */
  15. #define __seh_except(x) else if (int x = __sehContext.except())
  16.  
  17.  
  18. ///Helper object to handle SEH under Linux
  19. /** It is always accessible as __sehContext inside try-except block */
  20. class LinuxSEH {
  21. public:
  22.  
  23.     ///constructor - prepares context
  24.     LinuxSEH();
  25.     ///destructor - performs cleanup
  26.     ~LinuxSEH();
  27.  
  28.     ///called inside macro __seh_try
  29.     /** causes, that for cycle will be executed once */
  30.     inline bool enter()  {return swp = !swp;}
  31.     ///allows to convert context to jmp_buf to inicialize setjmp
  32.     operator __jmp_buf_tag *() { return jmpbuf;}
  33.     ///catches signal number after handler is executed. It is part of __seh_try macro
  34.     /**
  35.      * @param val value returned by setjmp. After handler is executed, it returns signal number
  36.      */
  37.     inline bool catchRes(int val) {return (signum = val) == 0;}
  38.  
  39.     ///used to implement __seh_except. Performs cleanup object's internal state and returns signal number
  40.     int except();
  41.    
  42.     ///signal handler
  43.     static void signalHandler(int sig);
  44.     ///initializes LinuxSEH signal actions - SIGSEGV, SIGBUS and SIGILL
  45.     static void init();
  46.     ///initializes LinuxSEH to catch specified signal
  47.     /**
  48.      * @param signum signal number to catch using SEH
  49.      */
  50.     static void initSignal(int signum);
  51.  
  52.  
  53. protected:
  54.  
  55.     jmp_buf jmpbuf;
  56.     __jmp_buf_tag *prevjmpbuf;
  57.     mutable bool swp;
  58.     int signum;
  59.  
  60.     static const struct sigaction standardSigAction;
  61. };
  62.  
  63. /// ----------------------- seh.cpp ------------------------------------------
  64. static __thread __jmp_buf_tag *globjmpbuf = 0;
  65.  
  66. void LinuxSEH::signalHandler(int sig) {
  67.     if (globjmpbuf) {
  68.  
  69.         siglongjmp(globjmpbuf ,sig);
  70.     }
  71.     char buff[256];
  72.     sprintf(buff,"Unhandled signal %d\n",sig);
  73.     write(2,buff,strlen(buff));
  74.     signal(sig,SIG_DFL);
  75. }
  76.  
  77.  
  78. LinuxSEH::LinuxSEH():swp(false) {
  79.     prevjmpbuf = globjmpbuf;
  80.     globjmpbuf  = jmpbuf;
  81. }
  82.  
  83. LinuxSEH::~LinuxSEH() {
  84.     if (globjmpbuf == jmpbuf) globjmpbuf = prevjmpbuf;
  85. }
  86.  
  87. int LinuxSEH::except() {
  88.     if (globjmpbuf == jmpbuf) globjmpbuf = prevjmpbuf;
  89.     return signum;
  90. }
  91.  
  92. static struct sigaction initSigAction() {
  93.     struct sigaction sig;
  94.     sig.sa_handler = &LinuxSEH::signalHandler;
  95.     sig.sa_flags = 0;
  96.     sig.sa_restorer = 0;
  97.     sigemptyset(&sig.sa_mask);
  98.     return sig;
  99. }
  100. const struct sigaction LinuxSEH::standardSigAction = initSigAction();
  101.  
  102. void LinuxSEH::init() {
  103.     initSignal(SIGSEGV);
  104.     initSignal(SIGBUS);
  105.     initSignal(SIGILL);
  106. }
  107.  
  108. void LinuxSEH::initSignal(int signum) {
  109.     sigaction(signum,&standardSigAction,0);
  110.  
  111. }
  112.  
  113. /// ----------------------- example.cpp ------------------------------------------
  114.  
  115.  
  116. int main() {
  117.  
  118.     LinuxSEH::init();
  119.     char *err = 0;
  120.     __seh_try {
  121.         __seh_try {
  122.             *err = 'A';
  123.         } __seh_except(signum) {
  124.             std::cout << "signal: " << signum << " handled A" << std::endl;
  125.             *err = 'B';
  126.         }
  127.     } __seh_except(signum) {
  128.         std::cout << "signal: " << signum << " handled B" << std::endl;
  129.     }
  130.  
  131.     LinuxSEH::initSignal(SIGTERM);
  132.     __seh_try {
  133.         std::cout << "terminate process please" << std::endl;
  134.         sleep(10);
  135.     } __seh_except(signum) {
  136.         std::cout << "signal: " << signum << " handled C" << std::endl;
  137.     }
  138.  
  139.     std::cout << "terminate process please" << std::endl;
  140.     sleep(10);
  141.  
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement