Oracle Solaris Studio 12.2:使用 dbx 调试程序

第 14 章 处理信号

本章说明如何使用 dbx 处理信号。dbx 支持 catch 命令,当 dbx 检测到出现在捕获列表中的任何信号时,此命令指示 dbx 停止程序。

dbx 命令 cont、step 和 next 均支持 -sig signal_name 选项,使用该选项可以恢复程序的执行,并使程序的行为像收到了在 cont -sig 命令中指定的信号一样。

本章由以下部分组成。

了解信号事件

在要将信号传送给正在调试的进程时,该信号会由内核重定向到 dbx。这时,通常会收到一个提示。而您有两种选择:

图 14–1 拦截和取消 SIGINT 信号

信号被传送的正常案例以及信号被 dbx 截获和取消的调试案例图。

此外,如果频繁收到某一信号,但又不想显示它,可以安排 dbx 自动转发该信号:


ignore signal # “ignore”

但是,仍然会将该信号转发给进程。一组缺省信号就是以这种方式自动转发的(请参见ignore 命令)。

捕获信号

缺省情况下,捕获列表包含 33 个以上可检测信号中的许多信号。(信号数目取决于操作系统和版本。)可通过从缺省捕获列表中添加或删除信号来更改缺省捕获列表。


注 –

dbx 接受的信号名称列表中包括 dbx 支持的各种版本 Solaris 操作环境所支持的所有信号。因此,dbx 可能接受当前正在运行的 Solaris 操作环境版本所不支持的信号。例如,dbx 可能接受 Solaris 9 OS 所支持的信号,即使当前运行的是 Solaris 7 OS。有关当前正在运行的 Solaris 操作系统所支持的信号列表,请参见 signal(3head) 手册页。


要查看当前正在捕获的那些 信号的列表,请键入不带 signal 参数的 catch。


(dbx) catch

要查看当前即使被程序检测到也会被 dbx 忽略的信号列表,请键入不带 signal 参数的 ignore。


(dbx) ignore

更改缺省信号列表

通过将信号名从一个列表移到另一个列表,可以控制由哪些信号导致程序停止。要移动信号名,将当前出现于某个列表的信号名作为参数提供给另一个列表即可。

例如,要将捕获列表中的 QUIT 和 ABRT 信号移到忽略列表中:


(dbx) ignore QUIT ABRT

捕获 FPE 信号(仅限 Solaris 平台)

使用要求进行浮点计算的代码编程的程序员经常需要调试程序中生成的异常。当出现被零除或上溢之类的浮点异常时,系统会返回一个合理的答案,作为导致异常的操作的结果。返回合理答案后,程序会继续安静地执行。Solaris 操作系统实现了异常合理答案的“IEEE 二进制浮点运算标准”定义。

因为返回了浮点异常的合理答案,所以异常不会自动触发信号 SIGFPE。缺省情况下,某些整数异常(如整数被零除和整数上溢)会触发信号 SIGFPE。

要查找导致异常的原因,需要在程序内设置陷阱处理程序,以使异常触发 SIGFPE 信号。(请参见 ieee_handler(3m) 手册页中的陷阱处理程序示例。)

可使用下列方式启用陷阱:

使用 ieee_handler 命令设置陷阱处理程序时,将设置硬件浮点状态寄存器中的陷阱启用掩码。此陷阱启用掩码会导致异常在运行时引发 SIGFPE 信号。

在编译含有该陷阱处理程序的程序后,将该程序装入 dbx。必须首先将 FPE 添加到 dbx 信号捕获列表中,才能捕获 SIGFPE 信号。


(dbx) catch FPE

缺省情况下,FPE 位于忽略列表中。

确定发生异常的位置

将 FPE 添加到捕获列表后,在 dbx 中运行程序。当出现要捕获的异常时,将引发 SIGFPE 信号,并且 dbx 会停止程序。然后,可以使用 dbx where 命令跟踪调用栈,以帮助查找程序中发生该异常的特定行号(请参见where 命令)。

确定导致异常的原因

要确定导致异常的原因,请使用 regs -f 命令显示浮点状态寄存器 (floating point state register, FSR)。查看寄存器的已产生的异常 (aexc) 和当前异常 (cexc) 字段,这些字段包含下列浮点异常条件位:

有关浮点状态寄存器的更多信息,请参见版本 8 (V8) 或版本 9 (V9) 的《SPARC Architecture Manual》(《SPARC 体系结构手册》)。有关更多讨论和示例,请参见《Numerical Computation Guide》(《数值计算指南》)。

向程序发送信号

dbx cont 命令支持 -sig signal 选项,使用该选项可以恢复程序的执行,并使程序的行为像收到了系统信号 signal 一样。

例如,如果程序具有相应于 SIGINT (^C) 的中断处理程序,则可以键入 ^C 来停止应用程序,并将控制返回到 dbx。如果您发出 cont 命令本身来继续执行程序,则永远不会执行该中断处理程序。要执行该中断处理程序,请将信号 SIGINT 发送到程序:


(dbx) cont -sig int

step 命令、next 命令和 detach 命令也接受 -sig。

自动处理信号

事件管理命令也可以把信号作为事件进行处理。这两种命令具有相同的作用。


(dbx) stop sig signal
(dbx) catch signal

如果需要将一些预编程操作关联起来,那么信号事件将是非常有用的。


(dbx) when sig SIGCLD {echo Got $sig $signame;}

在这种情况下,请确保首先将 SIGCLD 移至忽略列表。


(dbx) ignore SIGCLD