C 信号警报过早失效

C 信号警报过早失效,c,udp,signals,go-back-n,C,Udp,Signals,Go Back N,我有一个信号,其中我设置了一个回调处理程序,然后在我的函数中调用报警(1),这样我的程序将在1秒后超时。超时后,我希望它重试相同的阻塞调用recvfrom(),直到设置MAX\u尝试次数,即5次 问题: 退出程序前只重试2次。知道哪里出了问题吗 /* declate signal for setting alarm */ signal(SIGALRM, timeout_hdler); int attempts = 0; while(1) { if(attempts > MAX_A

我有一个
信号
,其中我设置了一个回调处理程序,然后在我的函数中调用
报警(1)
,这样我的程序将在1秒后超时。超时后,我希望它重试相同的阻塞调用
recvfrom()
,直到设置
MAX\u尝试次数
,即5次

问题:

退出程序前只重试2次。知道哪里出了问题吗

/* declate signal for setting alarm */
signal(SIGALRM, timeout_hdler);
int attempts = 0;

while(1) {
    if(attempts > MAX_ATTEMPTS) {
        printf("Connection is not working, EXITING program");
        s.curr_state = CLOSED;
        /* we assume connection is failing so we shut down */
        exit(-1);
    }

    if (s.curr_state == CLOSED) {

        printf("Sending SYN_packet with seqnum: %d...\n", SYN_packet->seqnum);

        if (sendto(sockfd, SYN_packet, sizeof(SYN_packet), 0, server, socklen) == -1) {
            perror("Sendto error");
            exit(-1);
        }

        s.curr_state = SYN_SENT;

        printf("Current state SYN_SENT: %d\n", s.curr_state);
    }

    if (s.curr_state == SYN_SENT) {



        alarm(1);
        attempts++;
        printf("\nAttempt number: %d\n", attempts);
        printf("Waiting for SYNACK_packet...\n");

        if (recvfrom(
                sockfd, SYNACK_packet, sizeof(*SYNACK_packet), 0, (struct sockaddr *) &server, &socklen) == -1)
        {
            if (errno != EINTR) {
                perror("Recvfrom SYNACK_packet error\n");
                s.curr_state = CLOSED;
                exit(-1);
            }
        }

        if ((SYNACK_packet->type == SYNACK) && (validate_packet(SYNACK_packet) == 1)) {

            printf("SYNACK_packet received\n");

            s.address = *(struct sockaddr *) &server;
            s.sock_len = socklen;
            s.curr_state = ESTABLISHED;
            s.seq_num = SYNACK_packet->seqnum;
            printf("Current state ESTABLISHED: %d\n", s.curr_state);
            return sockfd;
        }
    }
}
处理程序(除打印外不执行任何操作):

以下是我的控制台中的输出(来自
printf
语句):

为什么只尝试了两次就退出了程序?理想情况下,我希望在关闭连接之前重试5次(这是一个使用UDP的返回N实现)

更新

我通过重新安装
信号
信号(SIGALRM,timeout\u hdler)解决了这个问题在我的处理程序中。但为什么呢?我做错了吗

void timeout_hdler(int signum) {
    printf("TIMEOUT has occured with signum: %d", signum);
    signal(SIGALRM, timeout_hdler);
}

信号的语义取决于操作系统和libc。但是根据您在特定情况下的输出,在第一次调用处理程序函数后,信号处理程序将重置为默认值。如果再次触发信号,则默认值会导致程序退出,即
闹钟
和您在输出中看到的退出

发件人:

signal()的唯一可移植用途是将信号的配置设置为 信号灯或信号灯
在原始UNIX系统中,当建立 如果通过传递信号调用了using signal(),则信号的处理将重置为SIG_DFL,而系统没有 阻止信号的其他实例的传递

换句话说:不要使用
信号
。相反,您应该使用
sigaction

POSIX.1通过指定sigaction(2)解决了可移植性问题,sigaction(2)是 在调用信号处理程序时提供语义的显式控制 援引;使用该接口而不是signal()


这是一个很好的呼叫
sigaction
。这比仅仅使用
信号要复杂得多
想知道我是否可以在处理程序内部实例化信号…@Cyzanfar:有一种竞争,处理程序在调用信号处理程序之前重置为默认值,这意味着在处理程序重新建立之前的另一个警报将导致程序退出。但这很可能会影响您的具体案例。注意,您也可以通过使用SO_SNDTIMEO和SO_RCVTIMEO来执行w/o信号处理程序。感谢您的帮助@Steffen。有关信号处理器不可靠的原因,请参阅。请参阅并发布一个完整的示例。@LuisColorado这是一个完整的、最小的和可验证的示例,这是什么意思example@JonathanLeffler,信号在linux内核中不可靠,它们在BSD中,但在linux中不可靠,即使使用
sigaction(2)
。你只得到第一个信号,如果你收到了多个信号,而该信号被阻止,你不会得到多个信号。@LuisColorado我的情况下,它工作得很好。多亏了乔纳森
In Connect() with socket: 4, server: 2, socklen: 16
Sending SYN_packet with seqnum: 67...
Current state SYN_SENT: 1

Attempt number: 1
Waiting for SYNACK_packet...
TIMEOUT has occured with signum: 14
Attempt number: 2
Waiting for SYNACK_packet...
Alarm clock
void timeout_hdler(int signum) {
    printf("TIMEOUT has occured with signum: %d", signum);
    signal(SIGALRM, timeout_hdler);
}