udhcp: use poll() instead of select()
No binary (build failed)
—
(log yok)
| @@ -300,8 +300,8 @@ int udhcp_send_kernel_packet(struct dhcp_packet *dhcp_pkt, | |
| uint32_t dest_nip, int dest_port) FAST_FUNC; | |
| void udhcp_sp_setup(void) FAST_FUNC; | |
| - | int udhcp_sp_fd_set(fd_set *rfds, int extra_fd) FAST_FUNC; |
| - | int udhcp_sp_read(const fd_set *rfds) FAST_FUNC; |
| + | void udhcp_sp_fd_set(struct pollfd *pfds, int extra_fd) FAST_FUNC; |
| + | int udhcp_sp_read(struct pollfd *pfds) FAST_FUNC; |
| int udhcp_read_interface(const char *interface, int *ifindex, uint32_t *nip, uint8_t *mac) FAST_FUNC; | |
| @@ -935,9 +935,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |
| int timeout; /* must be signed */ | |
| unsigned already_waited_sec; | |
| unsigned opt; | |
| - | int max_fd; |
| int retval; | |
| - | fd_set rfds; |
| setup_common_bufsiz(); | |
| @@ -1063,7 +1061,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |
| * "continue" statements in code below jump to the top of the loop. | |
| */ | |
| for (;;) { | |
| - | struct timeval tv; |
| + | int tv; |
| + | struct pollfd pfds[2]; |
| struct d6_packet packet; | |
| uint8_t *packet_end; | |
| /* silence "uninitialized!" warning */ | |
| @@ -1078,16 +1077,15 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |
| * to change_listen_mode(). Thus we open listen socket | |
| * BEFORE we send renew request (see "case BOUND:"). */ | |
| - | max_fd = udhcp_sp_fd_set(&rfds, sockfd); |
| + | udhcp_sp_fd_set(pfds, sockfd); |
| - | tv.tv_sec = timeout - already_waited_sec; |
| - | tv.tv_usec = 0; |
| + | tv = timeout - already_waited_sec; |
| retval = 0; | |
| /* If we already timed out, fall through with retval = 0, else... */ | |
| - | if ((int)tv.tv_sec > 0) { |
| - | log1("waiting on select %u seconds", (int)tv.tv_sec); |
| + | if (tv > 0) { |
| + | log1("waiting on select %u seconds", tv); |
| timestamp_before_wait = (unsigned)monotonic_sec(); | |
| - | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); |
| + | retval = poll(pfds, 2, tv * 1000); |
| if (retval < 0) { | |
| /* EINTR? A signal was caught, don't panic */ | |
| if (errno == EINTR) { | |
| @@ -1222,8 +1220,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |
| /* select() didn't timeout, something happened */ | |
| /* Is it a signal? */ | |
| - | /* note: udhcp_sp_read checks FD_ISSET before reading */ |
| - | switch (udhcp_sp_read(&rfds)) { |
| + | /* note: udhcp_sp_read checks poll result before reading */ |
| + | switch (udhcp_sp_read(pfds)) { |
| case SIGUSR1: | |
| client_config.first_secs = 0; /* make secs field count from 0 */ | |
| already_waited_sec = 0; | |
| @@ -1258,7 +1256,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |
| } | |
| /* Is it a packet? */ | |
| - | if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds)) |
| + | if (listen_mode == LISTEN_NONE || !pfds[1].revents) |
| continue; /* no */ | |
| { | |
| @@ -1460,8 +1458,8 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |
| if (lease_seconds < 0x10) | |
| lease_seconds = 0x10; | |
| /// TODO: check for 0 lease time? | |
| - | if (lease_seconds >= 0x10000000) |
| - | lease_seconds = 0x0fffffff; |
| + | if (lease_seconds > 0x7fffffff / 1000) |
| + | lease_seconds = 0x7fffffff / 1000; |
| /* enter bound state */ | |
| timeout = lease_seconds / 2; | |
| bb_error_msg("lease obtained, lease time %u", | |
| @@ -1281,9 +1281,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |
| unsigned already_waited_sec; | |
| unsigned opt; | |
| IF_FEATURE_UDHCPC_ARPING(unsigned arpping_ms;) | |
| - | int max_fd; |
| int retval; | |
| - | fd_set rfds; |
| setup_common_bufsiz(); | |
| @@ -1432,7 +1430,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |
| * "continue" statements in code below jump to the top of the loop. | |
| */ | |
| for (;;) { | |
| - | struct timeval tv; |
| + | int tv; |
| + | struct pollfd pfds[2]; |
| struct dhcp_packet packet; | |
| /* silence "uninitialized!" warning */ | |
| unsigned timestamp_before_wait = timestamp_before_wait; | |
| @@ -1446,16 +1445,15 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |
| * to change_listen_mode(). Thus we open listen socket | |
| * BEFORE we send renew request (see "case BOUND:"). */ | |
| - | max_fd = udhcp_sp_fd_set(&rfds, sockfd); |
| + | udhcp_sp_fd_set(pfds, sockfd); |
| - | tv.tv_sec = timeout - already_waited_sec; |
| - | tv.tv_usec = 0; |
| + | tv = timeout - already_waited_sec; |
| retval = 0; | |
| /* If we already timed out, fall through with retval = 0, else... */ | |
| - | if ((int)tv.tv_sec > 0) { |
| - | log1("waiting on select %u seconds", (int)tv.tv_sec); |
| + | if (tv > 0) { |
| + | log1("waiting on select %u seconds", tv); |
| timestamp_before_wait = (unsigned)monotonic_sec(); | |
| - | retval = select(max_fd + 1, &rfds, NULL, NULL, &tv); |
| + | retval = poll(pfds, 2, tv * 1000); |
| if (retval < 0) { | |
| /* EINTR? A signal was caught, don't panic */ | |
| if (errno == EINTR) { | |
| @@ -1591,8 +1589,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |
| /* select() didn't timeout, something happened */ | |
| /* Is it a signal? */ | |
| - | /* note: udhcp_sp_read checks FD_ISSET before reading */ |
| - | switch (udhcp_sp_read(&rfds)) { |
| + | /* note: udhcp_sp_read checks poll result before reading */ |
| + | switch (udhcp_sp_read(pfds)) { |
| case SIGUSR1: | |
| client_config.first_secs = 0; /* make secs field count from 0 */ | |
| already_waited_sec = 0; | |
| @@ -1627,7 +1625,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |
| } | |
| /* Is it a packet? */ | |
| - | if (listen_mode == LISTEN_NONE || !FD_ISSET(sockfd, &rfds)) |
| + | if (listen_mode == LISTEN_NONE || !pfds[1].revents) |
| continue; /* no */ | |
| { | |
| @@ -1742,8 +1740,8 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |
| /* paranoia: must not be too small and not prone to overflows */ | |
| if (lease_seconds < 0x10) | |
| lease_seconds = 0x10; | |
| - | if (lease_seconds >= 0x10000000) |
| - | lease_seconds = 0x0fffffff; |
| + | if (lease_seconds > 0x7fffffff / 1000) |
| + | lease_seconds = 0x7fffffff / 1000; |
| } | |
| #if ENABLE_FEATURE_UDHCPC_ARPING | |
| if (opt & OPT_a) { | |
| @@ -794,7 +794,7 @@ static NOINLINE void send_inform(struct dhcp_packet *oldpacket) | |
| int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| - | int server_socket = -1, retval, max_sock; |
| + | int server_socket = -1, retval; |
| uint8_t *state; | |
| unsigned timeout_end; | |
| unsigned num_ips; | |
| @@ -891,10 +891,10 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |
| continue_with_autotime: | |
| timeout_end = monotonic_sec() + server_config.auto_time; | |
| while (1) { /* loop until universe collapses */ | |
| - | fd_set rfds; |
| + | struct pollfd pfds[2]; |
| struct dhcp_packet packet; | |
| int bytes; | |
| - | struct timeval tv; |
| + | int tv; |
| uint8_t *server_id_opt; | |
| uint8_t *requested_ip_opt; | |
| uint32_t requested_nip = requested_nip; /* for compiler */ | |
| @@ -906,16 +906,11 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |
| server_config.interface); | |
| } | |
| - | max_sock = udhcp_sp_fd_set(&rfds, server_socket); |
| - | if (server_config.auto_time) { |
| - | /* cast to signed is essential if tv_sec is wider than int */ |
| - | tv.tv_sec = (int)(timeout_end - monotonic_sec()); |
| - | tv.tv_usec = 0; |
| - | } |
| + | udhcp_sp_fd_set(pfds, server_socket); |
| + | tv = timeout_end - monotonic_sec(); |
| retval = 0; | |
| - | if (!server_config.auto_time || tv.tv_sec > 0) { |
| - | retval = select(max_sock + 1, &rfds, NULL, NULL, |
| - | server_config.auto_time ? &tv : NULL); |
| + | if (!server_config.auto_time || tv > 0) { |
| + | retval = poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); |
| } | |
| if (retval == 0) { | |
| write_leases(); | |
| @@ -926,7 +921,7 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |
| continue; | |
| } | |
| - | switch (udhcp_sp_read(&rfds)) { |
| + | switch (udhcp_sp_read(pfds)) { |
| case SIGUSR1: | |
| bb_error_msg("received %s", "SIGUSR1"); | |
| write_leases(); | |
| @@ -48,28 +48,29 @@ void FAST_FUNC udhcp_sp_setup(void) | |
| , signal_handler); | |
| } | |
| - | /* Quick little function to setup the rfds. Will return the |
| - | * max_fd for use with select. Limited in that you can only pass |
| - | * one extra fd */ |
| - | int FAST_FUNC udhcp_sp_fd_set(fd_set *rfds, int extra_fd) |
| + | /* Quick little function to setup the pfds. |
| + | * Limited in that you can only pass one extra fd. |
| + | */ |
| + | void FAST_FUNC udhcp_sp_fd_set(struct pollfd pfds[2], int extra_fd) |
| { | |
| - | FD_ZERO(rfds); |
| - | FD_SET(signal_pipe.rd, rfds); |
| + | pfds[0].fd = signal_pipe.rd; |
| + | pfds[0].events = POLLIN; |
| + | pfds[1].fd = -1; |
| if (extra_fd >= 0) { | |
| close_on_exec_on(extra_fd); | |
| - | FD_SET(extra_fd, rfds); |
| + | pfds[1].fd = extra_fd; |
| + | pfds[1].events = POLLIN; |
| } | |
| - | return signal_pipe.rd > extra_fd ? signal_pipe.rd : extra_fd; |
| } | |
| /* Read a signal from the signal pipe. Returns 0 if there is | |
| * no signal, -1 on error (and sets errno appropriately), and | |
| * your signal on success */ | |
| - | int FAST_FUNC udhcp_sp_read(const fd_set *rfds) |
| + | int FAST_FUNC udhcp_sp_read(struct pollfd pfds[2]) |
| { | |
| unsigned char sig; | |
| - | if (!FD_ISSET(signal_pipe.rd, rfds)) |
| + | if (!pfds[0].revents) |
| return 0; | |
| if (safe_read(signal_pipe.rd, &sig, 1) != 1) | |