diff options
Diffstat (limited to 'networking/udhcp/dhcpd.c')
-rw-r--r-- | networking/udhcp/dhcpd.c | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c index 093239536..19f94a2d7 100644 --- a/networking/udhcp/dhcpd.c +++ b/networking/udhcp/dhcpd.c | |||
@@ -853,6 +853,9 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
853 | /* Would rather not do read_config before daemonization - | 853 | /* Would rather not do read_config before daemonization - |
854 | * otherwise NOMMU machines will parse config twice */ | 854 | * otherwise NOMMU machines will parse config twice */ |
855 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); | 855 | read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE); |
856 | /* prevent poll timeout overflow */ | ||
857 | if (server_config.auto_time > INT_MAX / 1000) | ||
858 | server_config.auto_time = INT_MAX / 1000; | ||
856 | 859 | ||
857 | /* Make sure fd 0,1,2 are open */ | 860 | /* Make sure fd 0,1,2 are open */ |
858 | bb_sanitize_stdio(); | 861 | bb_sanitize_stdio(); |
@@ -914,21 +917,31 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
914 | } | 917 | } |
915 | 918 | ||
916 | udhcp_sp_fd_set(pfds, server_socket); | 919 | udhcp_sp_fd_set(pfds, server_socket); |
917 | tv = timeout_end - monotonic_sec(); | 920 | |
918 | retval = 0; | 921 | new_tv: |
919 | if (!server_config.auto_time || tv > 0) { | 922 | tv = -1; |
920 | retval = poll(pfds, 2, server_config.auto_time ? tv * 1000 : -1); | 923 | if (server_config.auto_time) { |
921 | } | 924 | tv = timeout_end - monotonic_sec(); |
922 | if (retval == 0) { | 925 | if (tv <= 0) { |
923 | write_leases(); | 926 | write_leases: |
924 | goto continue_with_autotime; | 927 | write_leases(); |
928 | goto continue_with_autotime; | ||
929 | } | ||
930 | tv *= 1000; | ||
925 | } | 931 | } |
926 | if (retval < 0 && errno != EINTR) { | 932 | |
927 | log1("error on select"); | 933 | /* Block here waiting for either signal or packet */ |
928 | continue; | 934 | retval = poll(pfds, 2, tv); |
935 | if (retval <= 0) { | ||
936 | if (retval == 0) | ||
937 | goto write_leases; | ||
938 | if (errno == EINTR) | ||
939 | goto new_tv; | ||
940 | /* < 0 and not EINTR: should not happen */ | ||
941 | bb_perror_msg_and_die("poll"); | ||
929 | } | 942 | } |
930 | 943 | ||
931 | switch (udhcp_sp_read(pfds)) { | 944 | if (pfds[0].revents) switch (udhcp_sp_read()) { |
932 | case SIGUSR1: | 945 | case SIGUSR1: |
933 | bb_error_msg("received %s", "SIGUSR1"); | 946 | bb_error_msg("received %s", "SIGUSR1"); |
934 | write_leases(); | 947 | write_leases(); |
@@ -938,12 +951,16 @@ int udhcpd_main(int argc UNUSED_PARAM, char **argv) | |||
938 | bb_error_msg("received %s", "SIGTERM"); | 951 | bb_error_msg("received %s", "SIGTERM"); |
939 | write_leases(); | 952 | write_leases(); |
940 | goto ret0; | 953 | goto ret0; |
941 | case 0: /* no signal: read a packet */ | ||
942 | break; | ||
943 | default: /* signal or error (probably EINTR): back to select */ | ||
944 | continue; | ||
945 | } | 954 | } |
946 | 955 | ||
956 | /* Is it a packet? */ | ||
957 | if (!pfds[1].revents) | ||
958 | continue; /* no */ | ||
959 | |||
960 | /* Note: we do not block here, we block on poll() instead. | ||
961 | * Blocking here would prevent SIGTERM from working: | ||
962 | * socket read inside this call is restarted on caught signals. | ||
963 | */ | ||
947 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); | 964 | bytes = udhcp_recv_kernel_packet(&packet, server_socket); |
948 | if (bytes < 0) { | 965 | if (bytes < 0) { |
949 | /* bytes can also be -2 ("bad packet data") */ | 966 | /* bytes can also be -2 ("bad packet data") */ |