来自信号处理程序的longjmp()

stt*_*ter 5 c unix signals longjmp

我正在使用以下代码尝试从用户读取输入并超时并在超过5秒后退出.这是通过setjmp/longjmp和SIGALRM信号的组合来实现的.

这是代码:

#include <stdio.h>
#include <setjmp.h>
#include <unistd.h>
#include <string.h>
#include <sys/signal.h>

jmp_buf buffer;

// this will cause t_gets() to return -2
void timeout() {
    longjmp(buffer, 1);
}

int t_gets(char* s, int t)
{
    char* ret;
    signal(SIGALRM, timeout);
    if (setjmp(buffer) != 0)
        return -2; // <--- timeout() will jump here
    alarm(t);
    // if fgets() does not return in t seconds, SIGALARM handler timeout()
    // will be called, causing t_gets() to return -2
    ret = fgets(s, 100, stdin);
    alarm(0);
    if (ret == NULL ) return -1;
    return strlen(s);
}

int main()
{
    char s[100];
    int z=t_gets(s, 5);
    printf("%d\n", z); 
}
Run Code Online (Sandbox Code Playgroud)

现在,我的问题是这个功能是否有任何问题.我已经读过从信号处理程序调用longjmp()可能有未定义的行为,究竟是什么呢?

此外,如果警报在fgets()返回后立即触发,但在调用警报(0)之前触发怎么办?即使用户确实输入了某些东西,它会导致函数返回-2吗?

后期编辑:我对改进代码的方法不感兴趣.我只是想知道它可能会失败.

Wer*_*sey 7

从longjmp的手册页:

POSIX未指定是否 longjmp()将恢复信号上下文.如果要保存和恢复信号掩码,请使用siglongjmp()

你的第二个问题:是的,函数将返回-2,因为longjmp()它会导致它进入setjmp(buffer)零件,但时间必须非常精确.