I have a signal where I set a callback handler and then in my function I call alarm(1) so that my program will time out after 1 second. Upon timing out I'd like it to retry to same blocking call recvfrom() until a set MAX_ATTEMPTS which is 5.
Problem:
It only retries 2 times before exiting the program. Any idea what might be going wrong?
/* 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;
}
}
}
The handler (which does nothing apart from printing):
void timeout_hdler(int signum) {
printf("TIMEOUT has occured with signum: %d", signum);
}
Here is the output in my console (from the printf statement):
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
Why is it exiting the program after only 2 attempts? Ideally I'd like it to retry 5 times before closing the connection (this is a Go Back N implementation using UDP)
UPDATE
I resolved the issue by reinstalling the signal: signal(SIGALRM, timeout_hdler); in my handler. But why is that? Am I doing this wrong?
void timeout_hdler(int signum) {
printf("TIMEOUT has occured with signum: %d", signum);
signal(SIGALRM, timeout_hdler);
}
The semantics of
signaldepends on the OS and libc. But according to your output in your specific case the signal handler handlers gets reset to the default after the first invocation of the handler function. The default then results in the program exit if the signal is triggered again, i.e. theAlarm clockand exit you see in the output.From the documentation of signal in Linux:
In other words: don't use
signal. Instead you should usesigaction: