信号发出后未捕获到异常 [英] Exception not caught after signal

查看:114
本文介绍了信号发出后未捕获到异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在我的代码中捕获终止信号,以在退出之前编写重启文件.我的解决方案基于以下

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;
  }
}

可以很好地抛出异常,但是我的catch块无法捕获它.程序以未捕获的异常InterruptException终止.我在MacOS上尝试了clang和gcc.知道为什么无法正确捕获异常吗?

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?

谢谢

使用g ++ 7.3.0编译时的输出:

Output when compiled with g++ 7.3.0:

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

使用Apple LLVM 9.0.0编译时的输出

Output when compiled with Apple LLVM 9.0.0

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

PS:似乎当我使用Apple LLVM进行编译时,有时会(但并非始终)捕获到异常,这使它变得更加奇怪.

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

推荐答案

在大多数系统上,信号处理程序使用的堆栈帧不是编译器为函数调用定义的标准函数堆栈帧.

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.

因此不支持抛出sig处理程序.

So throwing out of a sig handler is not supported.

用于Linux内核中信号处理的堆栈框架

在链接的问题中进行的讨论中,在Linux系统上,它们甚至没有使用相同的堆栈作为堆栈框架,而返回则需要跳回到系统功能以恢复原始用户堆栈.

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.

这篇关于信号发出后未捕获到异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆