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:
parent
d30b89c7ee
commit
4248c33a85
@ -307,7 +307,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
/* Goes to stdout (unless NOMMU) and possibly syslog */
|
/* Goes to stdout (unless NOMMU) and possibly syslog */
|
||||||
bb_info_msg("%s (v"BB_VER") started", applet_name);
|
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)) {
|
if (!client_config.clientid && !(opt & OPT_C)) {
|
||||||
client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
|
client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
|
||||||
client_config.clientid[OPT_DATA] = 1;
|
client_config.clientid[OPT_DATA] = 1;
|
||||||
@ -317,7 +317,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
|
|||||||
if (!client_config.vendorclass)
|
if (!client_config.vendorclass)
|
||||||
client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);
|
client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);
|
||||||
|
|
||||||
/* setup the signal pipe */
|
/* Set up the signal pipe */
|
||||||
udhcp_sp_setup();
|
udhcp_sp_setup();
|
||||||
|
|
||||||
state = INIT_SELECTING;
|
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 */
|
/* yah, I know, *you* say it would never happen */
|
||||||
timeout = INT_MAX;
|
timeout = INT_MAX;
|
||||||
continue; /* back to main loop */
|
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? */
|
/* Is it a packet? */
|
||||||
if (listen_mode != LISTEN_NONE && FD_ISSET(sockfd, &rfds)) {
|
if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds))
|
||||||
int len;
|
continue; /* no */
|
||||||
/* A packet is ready, read it */
|
|
||||||
|
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
/* A packet is ready, read it */
|
||||||
if (listen_mode == LISTEN_KERNEL)
|
if (listen_mode == LISTEN_KERNEL)
|
||||||
len = udhcp_recv_kernel_packet(&packet, sockfd);
|
len = udhcp_recv_kernel_packet(&packet, sockfd);
|
||||||
else
|
else
|
||||||
len = udhcp_recv_raw_packet(&packet, sockfd);
|
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));
|
bb_info_msg("Read error: %s, reopening socket", strerror(errno));
|
||||||
sleep(discover_timeout); /* 3 seconds by default */
|
sleep(discover_timeout); /* 3 seconds by default */
|
||||||
change_listen_mode(listen_mode); /* just close and reopen */
|
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;
|
already_waited_sec += (unsigned)monotonic_sec() - timestamp_before_wait;
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (packet.xid != xid) {
|
if (packet.xid != xid) {
|
||||||
log1("xid %x (our is %x), ignoring packet",
|
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;
|
already_waited_sec = 0;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
/* case BOUND, RELEASED: - ignore all packets */
|
/* case BOUND: - ignore all packets */
|
||||||
}
|
/* case 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* back to main loop */
|
||||||
} /* for (;;) - main loop ends */
|
} /* for (;;) - main loop ends */
|
||||||
|
|
||||||
ret0:
|
ret0:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user