Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I try to catch a termination signal to my code to write a restart file before exiting. My solution is based on this answer.

#include <exception>
#include <csignal>
#include <iostream>


class InterruptException : public std::exception
  {
   public:
    InterruptException(int _s) : signal_(_s) { }
    int signal() const noexcept
    {
      return this->signal_;
    }

   private:
    int signal_;
  };

  /// method to throw exception at signal interrupt
  void sig_to_exception(int s)
  {
    throw InterruptException(s);
  }

int main()
{
  // activate signal handling
  struct sigaction sigIntHandler;
  sigIntHandler.sa_handler = sig_to_exception;
  sigemptyset(&sigIntHandler.sa_mask);
  sigIntHandler.sa_flags = 0;
  sigaction(SIGINT, &sigIntHandler, NULL);

  try
  {
    for (std::size_t i = 0; i < 100000000; ++i)
    {
      std::cout  << i << std::endl;
    }
  }
  catch (const InterruptException& e)
  {
    std::cout << "Received signal " << e.signal() << std::endl;
    std::exit(1);
  }
  catch(...)
  {
    std::cout << "Other catch!" << std::endl;
  }
}

The exception gets thrown fine, however, my catch block does not catch it. The program terminates with an uncaught exception InterruptException. I tried with clang and gcc on MacOS. Any idea why the exception is not caught correctly?

Thanks

Output when compiled with g++ 7.3.0:

terminate called after throwing an instance of 'InterruptException'
   what():  std::exception
Abort trap: 6

Output when compiled with Apple LLVM 9.0.0

libc++abi.dylib: terminating with uncaught exception of type InterruptException: std::exception

PS: It seems when I compile with Apple LLVM the exception gets caught sometimes, but not all the time, which makes this even weirder.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
254 views
Welcome To Ask or Share your Answers For Others

1 Answer

On most system the stack frame used by the signal handler is not a standard function stack frame as defined by the compiler for function calls.

So throwing out of a sig handler is not supported.

Stack frame for signal handling in the Linux Kernel

From the discussion in the linked question, on a linux system they are not even using the same stack for the stack frame and returning requires jumping back to a system function to restore the original user stack.

Unless the OS is specifically designed to handle exceptions then this is not going to work.

The rule of thumb for signal handlers is to do as little as possible in a signal handler. Set a global flag that can be detected by your normal code then check that flag periodically in your normal code to see when the signal has happened.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share

548k questions

547k answers

4 comments

86.3k users

...