Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
268 views
in Technique[技术] by (71.8m points)

c++ - Exception not caught after signal

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

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

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...