udhcpc: fix a read error loop (e.g.: device is down) blocking TERM

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-06-26 23:23:16 +02:00
parent d30b89c7ee
commit 4248c33a85

View File

@ -307,7 +307,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
/* Goes to stdout (unless NOMMU) and possibly syslog */
bb_info_msg("%s (v"BB_VER") started", applet_name);
/* if not set, and not suppressed, setup the default client ID */
/* If not set, and not suppressed, set up the default client ID */
if (!client_config.clientid && !(opt & OPT_C)) {
client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
client_config.clientid[OPT_DATA] = 1;
@ -317,7 +317,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
if (!client_config.vendorclass)
client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);
/* setup the signal pipe */
/* Set up the signal pipe */
udhcp_sp_setup();
state = INIT_SELECTING;
@ -467,19 +467,45 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
/* yah, I know, *you* say it would never happen */
timeout = INT_MAX;
continue; /* back to main loop */
} /* if select timed out */
/* select() didn't timeout, something happened */
/* Is it a signal? */
/* note: udhcp_sp_read checks FD_ISSET before reading */
switch (udhcp_sp_read(&rfds)) {
case SIGUSR1:
perform_renew();
/* Start things over */
packet_num = 0;
/* Kill any timeouts because the user wants this to hurry along */
timeout = 0;
continue;
case SIGUSR2:
perform_release(requested_ip, server_addr);
timeout = INT_MAX;
continue;
case SIGTERM:
bb_info_msg("Received SIGTERM");
if (opt & OPT_R) /* release on quit */
perform_release(requested_ip, server_addr);
goto ret0;
}
/* select() didn't timeout, something did happen. */
/* Is it a packet? */
if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
int len;
/* A packet is ready, read it */
if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds))
continue; /* no */
{
int len;
/* A packet is ready, read it */
if (listen_mode == LISTEN_KERNEL)
len = udhcp_recv_kernel_packet(&packet, sockfd);
else
len = udhcp_recv_raw_packet(&packet, sockfd);
if (len == -1) { /* error is severe, reopen socket */
if (len == -1) {
/* Error is severe, reopen socket */
bb_info_msg("Read error: %s, reopening socket", strerror(errno));
sleep(discover_timeout); /* 3 seconds by default */
change_listen_mode(listen_mode); /* just close and reopen */
@ -490,6 +516,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
if (len < 0)
continue;
}
if (packet.xid != xid) {
log1("xid %x (our is %x), ignoring packet",
@ -629,34 +656,10 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
already_waited_sec = 0;
}
continue;
/* case BOUND, RELEASED: - ignore all packets */
}
continue; /* back to main loop */
}
/* select() didn't timeout, something did happen.
* But it wasn't a packet. It's a signal pipe then. */
{
int signo = udhcp_sp_read(&rfds);
switch (signo) {
case SIGUSR1:
perform_renew();
/* start things over */
packet_num = 0;
/* Kill any timeouts because the user wants this to hurry along */
timeout = 0;
break;
case SIGUSR2:
perform_release(requested_ip, server_addr);
timeout = INT_MAX;
break;
case SIGTERM:
bb_info_msg("Received SIGTERM");
if (opt & OPT_R) /* release on quit */
perform_release(requested_ip, server_addr);
goto ret0;
}
/* case BOUND: - ignore all packets */
/* case RELEASED: - ignore all packets */
}
/* back to main loop */
} /* for (;;) - main loop ends */
ret0: