C 中的 alarm() 和 SIGALRM 问题

Posted

技术标签:

【中文标题】C 中的 alarm() 和 SIGALRM 问题【英文标题】:Issue with alarm() and SIGALRM in C 【发布时间】:2011-02-07 23:30:31 【问题描述】:

我遇到了一个似乎没有被触发的 SIGALRM 问题。为了简化代码,我使用 signal() 而不是 sigaction()。

目的是有一些循环读取,但在 x 秒后,在再次读取之前重新初始化所有变量。我为此使用了闹钟。

volatile sig_atomic_t restartBool;

void    catch_alarm(int sig)

    fprintf(stderr, "ALARM CALLED\n");
    restartBool = 1;


int     main(void)


     int n, fd_in = 0;
     char newChar;

    signal(SIGALRM, catch_alarm);

    while (1)                      /* main loop */

            restartBool = 0;

            // Set a timer before we start reading
            alarm(2);

            while (restartBool == 0 && (n = read(fd_in, &newChar, 1)) == 1)        /* parse input */
                /* ..... */
            
            fprintf(stderr, "EXITED THE LOOP");

            // Cancel the alarm/timer
            alarm(0);
    

catch_alarm() 函数中的 fprintf() 语句从未被调用,我不知道为什么(我在 Linux 上运行)。

任何帮助都会很棒,

非常感谢,

杰瑞

【问题讨论】:

-1 用于伪造代码。代码没有按原样编译,当我将int n, fd_in=0, newChar; 添加到main 的开头时,它工作得很好(打印了消息)。 fprintf 不可重入:从信号处理程序调用是不安全的,因为在传递信号时您可能正在调用它。 抱歉 R..,我试图让代码更简洁,我已经解决了这个问题。它不适合我打印,我听说某些论坛上某些版本的 Linux 可能存在问题,但我不确定是否会出现这种情况。它绝对不会为我打印任何东西。 谢谢亚当,我没想到。我只是将其保留用于测试目的,直到它实际打印一次,然后我将其删除。 fprintf 不是异步信号安全的,但这似乎不是问题。当然,如果您以这种方式调用未定义的行为,任何事情都可能发生,但现实世界的影响几乎肯定会是崩溃或死锁。如果您想测试这是否是问题,请使用 write(2, "message\n", 8);而不是信号处理程序中的fprintf 【参考方案1】:

您的读取很可能在您的计时器关闭之前很久就返回 0(没有剩余字节)。 IE,循环正在退出,因为您的数据不足,然后您正在取消警报(尚未响起)。

【讨论】:

以上是关于C 中的 alarm() 和 SIGALRM 问题的主要内容,如果未能解决你的问题,请参考以下文章

为啥 alarm() 导致 fgets() 停止等待?

信号和报警功能

SIGALRM信号和SIGCHID信号

alarm是啥指令200smart

nginx之SIGALRM和SIGCHID信号

函数返回时停止 SIGALRM