【问题标题】:What is the correct way to force an app to core dump and quit?强制应用程序进行核心转储和退出的正确方法是什么?
【发布时间】:2011-04-13 11:08:37
【问题描述】:

我刚刚遇到了一些使用 kill 系统调用向应用发送 SIGSEGV 信号的代码。这背后的基本原理是,这将迫使应用程序进行核心转储并退出。这对我来说似乎很错误,这是正常做法吗?

【问题讨论】:

标签: c++ c core signals


【解决方案1】:

如果您希望生成核心转储,SIGQUIT 是发送给程序的正确信号。 kill 是发送信号的正确命令行程序(它的名字当然不好,因为不是所有的信号都会杀死程序)。

注意,您不应向程序发送随机信号,并非所有信号都会产生核心转储。其中许多将由程序本身处理,要么被消耗,要么被忽略,要么引发其他处理。因此发送 SIGSEGV 是错误的。


GCC 说: http://www.gnu.org/s/libc/manual/html_node/Termination-Signals.html

POSIX/Unix 说: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/signal.h.html

【讨论】:

  • +1 但在这里引用会大有帮助……POSIX 实际上对核心转储有什么看法?
  • 好的。第二个文档用“A”标记表示中止,并可能生成一个核心文件。
  • 不幸的是,应用程序可能已经为 SIGQUIT 安装了一个信号处理程序,从而阻止了默认行为。在这种情况下,您将不再获得核心转储。您是否会 - 并且只有这样 - 认为在默认情况下尝试滥用其他信号之一生成核心转储(SIGSEGV、SIGILL、...)是合法的?
【解决方案2】:

是的。 kill 有点名不副实——它可以发送任何信号。 kill 有很多用途,根本不会导致进程被杀死!

【讨论】:

  • +1: kill -1 通常用于发送 SIGHUP,这通常会导致使用此功能编写的程序重新加载其配置。 (例如:sendmail、init 等)
  • SIGQUIT 是获得核心转储的一个。
【解决方案3】:

如果你想让一个应用程序从另一个程序中转储它的核心,几乎唯一的方法就是通过一个信号。 SEGV 可以解决这个问题。或者,您可以将调试器连接到程序并冻结它并查看它的寄存器等而不杀死它。

如果您想从应用程序中转储内核,有更好的方法可以做到这一点,例如通过 assert()。

所以,不,将 SEGV 发送到程序并不是特别错误。您还可以发送诸如 SIGILL 之类的非法指令,或除以零信号。一切都好。

【讨论】:

  • 不,这不好。这些信号都有特定的含义,程序对它们的反应也不同。它们不会全部杀死程序,也不会全部产生核心转储。
【解决方案4】:

在 Unix/Linux 中执行此操作的方法是调用 abort(),它将 SIGABORT 发送到当前进程。另一个选项是 raise(),您可以在其中指定要发送到当前进程的信号。

【讨论】:

  • +1 表示 raiseabort 当目标是你自己时更有意义。
【解决方案5】:

Richard Stevens(_UNIX 环境中的高级编程)写道:

内核的生成是大多数Unix的一个实现特性。它不是 POSIX.1 的一部分。

他列出了 12 个信号,其默认操作是用一个内核终止(ANSI:SIGABRT、SIGFPE、SIGILL、SIGSEGV、POSIX:SIGQUIT,其他:SIGBUS、SIGEMT、SIGIOT、SIGSYS、SIGTRAP、SIGXCPU、SIGXFSZ),所有的它们是可覆盖的(不可覆盖的两个信号是 SIGKILL 和 SIGSTOP)。

我从未见过不使用默认信号处理程序来生成核心的方法。

因此,如果您的目标是生成核心并停止,最好选择一个其默认处理程序完成工作的信号(SIGSEGV 完成工作),如果您正在使用它,请重置该信号的默认处理程序,然后使用杀。

【讨论】:

  • Emacs 有一种无需信号处理程序即可生成核心的方法。在程序的构建过程中使用它来保存一个已经加载了 elisp 的新 emacs 二进制文件,这是一个可怕的 hack...
  • @R.. 上次我检查时,emacs 的方式是通过了解可执行文件和核心文件格式自行编写核心文件。
  • 是的,它就是这样做的。 XEmacs 有一个更明智的方法 - 它将所有 elisp 代码/数据分配到它自己管理的堆中(在 .data 部分中),将其保存到磁盘,然后在运行时使用 mmapMAP_FIXED 来映射它回到它的“堆”之上。
猜你喜欢
  • 1970-01-01
  • 2016-11-23
  • 1970-01-01
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
  • 1970-01-01
  • 2010-09-26
  • 2020-09-27
相关资源
最近更新 更多