klayout 源码分析系列续 程序崩溃时显示调用堆栈

klayout 有个很酷的功能:程序崩溃时会有对话框弹出显示错误所在行号和程序的函数调用堆栈,这对解决bug非常有帮助。

下面就分析下这个功能的实现机制。

首先,klayout在程序启动时,加了崩溃处理的Handler.

//laySignalHandler.cc

void install_signal_handlers ()
{
  struct sigaction act;
  act.sa_sigaction = signal_handler;
  sigemptyset (&act.sa_mask);
  act.sa_flags = SA_SIGINFO;
#if !defined(__APPLE__)
  act.sa_restorer = 0;
#endif

  sigaction (SIGSEGV, &act, NULL);
  sigaction (SIGILL, &act, NULL);
  sigaction (SIGFPE, &act, NULL);
  sigaction (SIGABRT, &act, NULL);
  sigaction (SIGBUS, &act, NULL);
}

之后,在程序崩溃时,会运行设置的signal_handler函数。

void signal_handler (int signo, siginfo_t *si, void *)
{
//  InformationBox::Instance()->hide();
  void *array [100];

  bool can_resume = (signo != SIGILL);

  size_t nptrs = backtrace (array, sizeof (array) / sizeof (array[0]));

  std::string text;
  text += tl::sprintf ("Signal number: %d\n", signo);
  text += tl::sprintf ("Address: 0x%lx\n", (unsigned long) si->si_addr);
  text += std::string ("Program Version: ") +
            lay::Version::name () + " " +
            lay::Version::version () + " (" + lay::Version::subversion () + ")\n";

  std::auto_ptr<CrashMessage> msg;

  bool has_gui = s_sh_has_gui && lay::ApplicationBase::instance () && lay::ApplicationBase::instance ()->has_gui ();

  if (has_gui) {
    msg.reset (new CrashMessage (0, false, tl::to_qstring (text) + QObject::tr ("\nCollecting backtrace ..")));
    msg->show ();
    lay::ApplicationBase::instance ()->qapp_gui ()->setOverrideCursor (Qt::WaitCursor);
  }

  text += std::string ("\nBacktrace:\n");

#if 0

  //  the approach with backtrace_symbols - this does not resolve shared object symbols
  char **symbols = backtrace_symbols (array, nptrs);
  if (symbols == NULL) {
    text += "-- Unable to obtain stack trace --\n";
  } else {
    for (size_t i = 2; i < nptrs; i++) {
      text += std::string (symbols [i]) + "\n";
    }
  }
  free(symbols);

#else

  //  the more elaborate approach using the addr2line external tool to obtain debug information
  //  (if available)

  const char *addr2line_call = "addr2line -C -s -f -e '%s' 0x%lx";

通过调用命令行程序 addr2line 显示错误堆栈。

关于addr2line的详细介绍,可参考 addr2line探秘

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天天进步2015

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值