【问题标题】:Where is a signal coming from哪里来的信号
【发布时间】:2011-11-10 03:27:25
【问题描述】:

我在 solaris 服务器上运行了一个 shell 脚本,它是一个非常复杂的脚本,它会调用其他一些 shell 或 perl 脚本,整个执行过程会花费很长时间——几个小时。

奇怪的是,它总是异常退出。我使用“truss”命令来记录shell进程的系统调用。它表明原因似乎是信号#15 SIGTERM 的到来。但我不知道信号#15 来自哪里?有什么方法可以检测信号来自哪个进程?

我的服务器信息:

uname -a
SunOS zsups379 5.10 Generic_144488-07 sun4u sparc SUNW,Sun-Fire-880

truss输出的切片(23528为主进程,25213为23528的子进程):

25213/2:        read(8, "17A6 G8A078A 58E15 P9E 5".., 8192)     = 8192

25213/1:            Received signal #15, SIGTERM, in lwp_wait() [caught]

23528:      Received signal #15, SIGTERM, in waitid() [caught]

25213/2:        write(9, " X #85 f @F5 Z88CAFB J\n".., 515)     = 515

23528:  waitid(P_ALL, 0, 0xFFBFD958, WEXITED|WTRAPPED|WSTOPPED|WCONTINUED) Err#91 ERESTART

25213/1:        lwp_wait(2, 0xFFBFD39C)                         Err#91 ERESTART

25213/1:        lwp_sigmask(SIG_SETMASK, 0xFFBFFEFF, 0x0000FFF7) = 0xFFBFFEFF [0x0000FFFF]

23528:  lwp_sigmask(SIG_SETMASK, 0x00004000, 0x00000000) = 0xFFBFFEFF [0x0000FFFF]
....

【问题讨论】:

    标签: shell unix solaris signals


    【解决方案1】:

    您可以使用与该脚本类似的 dtrace 脚本轻松跟踪发送到您的进程的所有信号:

    proc:::signal-send
    / args[2] == 15 /
    {
        printf("Process %d (%s) killing %d (%s)\n",
                pid, execname, args[1]->pr_pid, args[1]->pr_fname);
    }
    

    【讨论】:

    • 谢谢。这对我来说是一个新的方向,因为我以前从未使用过 dtrace。我会尝试一下。
    • 事实上,在 Solaris 系统上,您会发现 /usr/demo/dtrace/sig.d 作为 DTrace 可以执行的示例。只需尝试一下。
    • @FrankH:我建议(现在已修复)的脚本针对的是 user1038919 的信号,一旦发生就会显示任何 SIGTERM。演示是对所有信号进行汇总统计,这当然很有趣,但不太适合启动调查。
    【解决方案2】:

    信号作为 IPC(进程间通信)方法的一个问题是无法找出信号的来源。 因为您可能看不到 @ 987654323@ 在truss 输出中,您可以假设信号不是来自桁架进程。因此,它必须来自其他地方——要么(也许,但不太可能)系统本身,要么(更有可能)另一个进程。

    我的记忆力下降了——部分原因是我从未使用过这种机制......

    在 POSIX 中有带有 SA_SIGINFO 标志的 sigaction() 系统调用和在 <signal.h> 中定义的 siginfo_t 结构。

    <signal.h> 标头应将siginfo_t 类型定义为结构,该结构应至少包括以下成员:

    int           si_signo  Signal number. 
    int           si_code   Signal code. 
    int           si_errno  If non-zero, an errno value associated with 
                            this signal, as described in <errno.h>. 
    pid_t         si_pid    Sending process ID. 
    uid_t         si_uid    Real user ID of sending process. 
    void         *si_addr   Address of faulting instruction. 
    int           si_status Exit value or signal. 
    long          si_band   Band event for SIGPOLL. 
    union sigval  si_value  Signal value.
    

    【讨论】:

    • 是的,我也注意到了 siginfo_t 类型。实际上,我可以编写一个信号处理程序来在我的主进程中获取 siginfo_t,例如我的示例中的进程 23528,并且信号来自它的子进程 25213。但是,如果信号是逐层发出和传输的,例如,进程 25213 不是真正的信号发送者,它只是捕获其他进程产生的信号。进程 25213 的源代码对我来说是不可更改的,因此我无法为其添加信号处理程序。所以就像那样,我不能将信号处理程序添加到每一层子进程。如何获取原始发件人进程?
    猜你喜欢
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    • 2010-12-14
    • 2014-04-04
    • 1970-01-01
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    相关资源
    最近更新 更多