3

我个人讨厌这类问题,但我被困住了。我有一个正在尝试在Ubuntu 12.4上运行的程序 (内核:Linux 3.2.0-39-generic-pae #62-Ubuntu SMP i686 i686 i386 GNU/Linux;编译器:gcc(Ubuntu/Linaro 4.6.3- 1ubuntu5)4.6.3)

#include    <stdio.h>
#include    <signal.h>
#include    <unistd.h>

/*
 * sleep1.c
 *      purpose show how sleep works
 *      usage   sleep1
 *      info    sets handler, sets alarm, pauses, then returns
 */

int main()
{
    void    onbell(int);

    printf("about to sleep for 4 seconds\n");
    signal(SIGALRM, onbell);            /* catch it */
    alarm(4);                   /* set clock    */
    pause();                    /* do nothing   */
    printf("Morning so soon?\n");           /* back to work */
    return 0;
}

void
onbell(int s)
{
    printf("Alarm received from kernel\n");
}

问题是,SIGALRM永远不会通过。如果我在上面运行strace,最后三行是:

rt_sigaction(SIGALRM, {0x80484c1, [ALRM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
alarm(4)                                = 0
pause(

暂停永远不会回来。当我在使用内核报告自身的系统上运行相同的代码时:Linux 2.6.24-32-generic i686 GNU/Linux;编译器:gcc (GCC) 4.2.4 (Ubuntu 4.2.4-1ubuntu4)使用 strace 运行的相同代码显示:

rt_sigaction(SIGALRM, {0x8048470, [ALRM], SA_RESTART}, {SIG_DFL}, 8) = 0
alarm(4)                                = 0
pause()                                 = ? ERESTARTNOHAND (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
write(1, "Alarm received from kernel\n", 27Alarm received from kernel
) = 27

知道为什么在Ubuntu 12.4系统上从未收到警报,或者可以做些什么来弄清楚发生了什么?

4

2 回答 2

1

您不能从信号处理程序中安全地调用 printf() 或相当数量的其他 i/o 函数。它有时有效,但不可靠。它不是异步信号安全的。查看其他列表:http: //man7.org/linux/man-pages/man7/signal.7.html

然而,它有时会“意外”起作用,使人们认为它通常是可以接受的。

尝试在信号处理程序内增加一个变量,然后在信号处理程序外检查它的值是否发生变化。

于 2013-04-01T02:19:10.680 回答
0

我认为问题在于信号永远不会被触发的可能性。毕竟,strace 显示rt_sigaction返回 0 表示设置信号配置成功。我认为SIGALRM信号根本没有被发送。

编辑:似乎是这样。我希望@Gonzalo 不介意我引用他发布的标题为“SIGALRM 永不触发”的 VirtualBox票证。你说你在虚拟盒子上测试。它似乎确实反映了这种行为。

于 2013-04-01T02:10:38.770 回答