* "continue" statements in code below jump to the top of the loop.
*/
for (;;) {
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
+ unsigned timestamp_before_wait;
if (listen_mode != LISTEN_NONE && sockfd < 0) {
if (listen_mode == LISTEN_KERNEL)
}
max_fd = udhcp_sp_fd_set(&rfds, sockfd);
+ tv.tv_sec = timeout;
+ tv.tv_usec = 0;
retval = 0; /* If we already timed out, fall through, else... */
if (tv.tv_sec > 0) {
+ timestamp_before_wait = (unsigned)monotonic_sec();
DEBUG("Waiting on select...");
retval = select(max_fd + 1, &rfds, NULL, NULL, &tv);
- }
-
- if (retval < 0) {
- /* EINTR? signal was caught, don't panic */
- if (errno != EINTR) {
+ if (retval < 0) {
+ /* EINTR? A signal was caught, don't panic */
+ if (errno == EINTR)
+ continue;
/* Else: an error occured, panic! */
bb_perror_msg_and_die("select");
}
- continue;
}
/* If timeout dropped to zero, time to become active:
/* send a request packet */
send_renew(xid, server_addr, requested_ip); /* unicast */
t1 += (t2 - t1) / 2;
- timeout = t1 - ((int)monotonic_sec() - timestamp_got_lease);
+ timeout = t1 - ((unsigned)monotonic_sec() - timestamp_got_lease);
continue;
}
/* Timed out, enter rebinding state */
/* send a request packet */
send_renew(xid, 0, requested_ip); /* broadcast */
t2 += (lease_seconds - t2) / 2;
- timeout = t2 - ((int)monotonic_sec() - timestamp_got_lease);
+ timeout = t2 - ((unsigned)monotonic_sec() - timestamp_got_lease);
continue;
}
/* Timed out, enter init state */
else
len = get_raw_packet(&packet, sockfd);
+ /* If this packet will turn out to be unrelated/bogus,
+ * we will go back and wait for next one.
+ * Be sure timeout is properly decreased. */
+ timeout -= (unsigned)monotonic_sec() - timestamp_before_wait;
+
if (len == -1) { /* error is severe, reopen socket */
DEBUG("error on read, %s, reopening socket", strerror(errno));
change_listen_mode(listen_mode); /* just close and reopen */
ret0:
retval = 0;
ret:
- /*if (client_config.pidfile) - remove_pidfile has it's own check */
+ /*if (client_config.pidfile) - remove_pidfile has its own check */
remove_pidfile(client_config.pidfile);
return retval;
}