introduce safe_poll (fixes a problem in top)
No binary (build failed)
—
(log yok)
| @@ -2139,7 +2139,7 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds | |
| pfd[0].fd = 0; | |
| pfd[0].events = POLLIN; | |
| - | return poll(pfd, 1, hund*10) > 0; |
| + | return safe_poll(pfd, 1, hund*10) > 0; |
| } | |
| #define readbuffer bb_common_bufsiz1 | |
| @@ -2221,7 +2221,7 @@ static char readit(void) // read (maybe cursor) key from stdin | |
| pfd[0].events = POLLIN; | |
| // Wait 50 ms | |
| // keep reading while there are input chars and room in buffer | |
| - | while (poll(pfd, 1, 50) > 0 && n <= (MAX_LINELEN - 5)) { |
| + | while (safe_poll(pfd, 1, 50) > 0 && n <= (MAX_LINELEN - 5)) { |
| // read the rest of the ESC string | |
| int r = read(0, readbuffer + n, MAX_LINELEN - n); | |
| if (r > 0) | |
| @@ -451,8 +451,14 @@ extern FILE *fopen_or_warn(const char *filename, const char *mode); | |
| /* "Opens" stdin if filename is special, else just opens file: */ | |
| extern FILE *fopen_or_warn_stdin(const char *filename); | |
| + | /* Wrapper which restarts poll on EINTR or ENOMEM. |
| + | * On other errors complains [perror("poll")] and returns. |
| + | * Warning! May take (much) longer than timeout_ms to return! |
| + | * If this is a problem, use bare poll and open-code EINTR/ENOMEM handling */ |
| + | int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout_ms); |
| + | |
| /* Convert each alpha char in str to lower-case */ | |
| - | extern char* str_tolower(char *str); |
| + | char* str_tolower(char *str); |
| char *utoa(unsigned n); | |
| char *itoa(int n); | |
| @@ -71,6 +71,7 @@ lib-y += recursive_action.o | |
| lib-y += remove_file.o | |
| lib-y += restricted_shell.o | |
| lib-y += run_shell.o | |
| + | lib-y += safe_poll.o |
| lib-y += safe_strncpy.o | |
| lib-y += safe_write.o | |
| lib-y += setup_environment.o | |
| @@ -0,0 +1,34 @@ | |
| + | /* vi: set sw=4 ts=4: */ |
| + | /* |
| + | * Utility routines. |
| + | * |
| + | * Copyright (C) 2007 by Denys Vlasenko <[email protected]> |
| + | * |
| + | * Licensed under GPLv2, see file LICENSE in this tarball for details. |
| + | */ |
| + | |
| + | #include "libbb.h" |
| + | |
| + | /* Wrapper which restarts poll on EINTR or ENOMEM. |
| + | * On other errors does perror("poll") and returns. |
| + | * Warning! May take longer than timeout_ms to return! */ |
| + | int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout) |
| + | { |
| + | while (1) { |
| + | int n = poll(ufds, nfds, timeout); |
| + | if (n >= 0) |
| + | return n; |
| + | /* Make sure we inch towards completion */ |
| + | if (timeout > 0) |
| + | timeout--; |
| + | /* E.g. strace causes poll to return this */ |
| + | if (errno == EINTR) |
| + | continue; |
| + | /* Kernel is very low on memory. Retry. */ |
| + | /* I doubt many callers would handle this correctly! */ |
| + | if (errno == ENOMEM) |
| + | continue; |
| + | bb_perror_msg("poll"); |
| + | return n; |
| + | } |
| + | } |
| @@ -10,7 +10,7 @@ | |
| #include "libbb.h" | |
| /* Like strncpy but make sure the resulting string is always 0 terminated. */ | |
| - | char * safe_strncpy(char *dst, const char *src, size_t size) |
| + | char *safe_strncpy(char *dst, const char *src, size_t size) |
| { | |
| if (!size) return dst; | |
| dst[--size] = '\0'; | |
| @@ -105,8 +105,7 @@ int microcom_main(int argc, char **argv) | |
| pfd[1].events = POLLIN; | |
| while (1) { | |
| int i; | |
| - | while (-1 == poll(pfd, 2, -1) && EINTR == errno) |
| - | continue; |
| + | safe_poll(pfd, 2, -1); |
| for (i = 0; i < 2; ++i) { | |
| if (pfd[i].revents & POLLIN) { | |
| len = read(pfd[i].fd, bb_common_bufsiz1, COMMON_BUFSIZE); | |
| @@ -1073,12 +1073,8 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post | |
| } | |
| /* Now wait on the set of sockets */ | |
| - | count = poll(pfd, 3, -1); |
| + | count = safe_poll(pfd, 3, -1); |
| if (count <= 0) { | |
| - | #if 0 |
| - | if (errno == EINTR) |
| - | continue; |
| - | #endif |
| #if 0 | |
| if (waitpid(pid, &status, WNOHANG) <= 0) { | |
| /* Weird. CGI didn't exit and no fd's | |
| @@ -225,7 +225,7 @@ static int tftp( USE_GETPUT(const int cmd,) | |
| /* Receive packet */ | |
| /*pfd[0].fd = socketfd;*/ | |
| pfd[0].events = POLLIN; | |
| - | switch (poll(pfd, 1, waittime_ms)) { |
| + | switch (safe_poll(pfd, 1, waittime_ms)) { |
| unsigned from_port; | |
| case 1: | |
| from->len = peer_lsa->len; | |
| @@ -262,7 +262,7 @@ static int tftp( USE_GETPUT(const int cmd,) | |
| goto send_again; /* resend last sent pkt */ | |
| default: | |
| - | bb_perror_msg("poll"); |
| + | /*bb_perror_msg("poll"); - done in safe_poll */ |
| goto ret; | |
| } | |
| process_pkt: | |
| @@ -543,7 +543,7 @@ wait_for_reply(int sock, struct sockaddr_in *fromp) | |
| pfd[0].fd = sock; | |
| pfd[0].events = POLLIN; | |
| - | if (poll(pfd, 1, waittime * 1000) > 0) |
| + | if (safe_poll(pfd, 1, waittime * 1000) > 0) |
| cc = recvfrom(sock, packet, sizeof(packet), 0, | |
| (struct sockaddr *)fromp, &fromlen); | |
| return cc; | |
| @@ -81,12 +81,9 @@ int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *i | |
| unsigned prevTime = monotonic_us(); | |
| pfd[0].events = POLLIN; | |
| - | r = poll(pfd, 1, timeout_ms); |
| + | r = safe_poll(pfd, 1, timeout_ms); |
| if (r < 0) { | |
| - | if (errno != EINTR) { |
| - | bb_perror_msg("poll"); |
| - | break; |
| - | } |
| + | break; |
| } else if (r) { | |
| if (read(s, &arp, sizeof(arp)) < 0) | |
| break; | |
| @@ -300,7 +300,12 @@ int zcip_main(int argc, char **argv) | |
| VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", | |
| timeout_ms, intf, nprobes, nclaims); | |
| - | switch (poll(fds, 1, timeout_ms)) { |
| + | |
| + | switch (safe_poll(fds, 1, timeout_ms)) { |
| + | |
| + | default: |
| + | /*bb_perror_msg("poll"); - done in safe_poll */ |
| + | return EXIT_FAILURE; |
| // timeout | |
| case 0: | |
| @@ -388,6 +393,7 @@ int zcip_main(int argc, char **argv) | |
| break; | |
| } // switch (state) | |
| break; // case 0 (timeout) | |
| + | |
| // packets arriving | |
| case 1: | |
| // We need to adjust the timeout in case we didn't receive | |
| @@ -519,13 +525,9 @@ int zcip_main(int argc, char **argv) | |
| nclaims = 0; | |
| break; | |
| } // switch state | |
| - | |
| break; // case 1 (packets arriving) | |
| - | default: |
| - | why = "poll"; |
| - | goto bad; |
| } // switch poll | |
| - | } |
| + | } // while (1) |
| bad: | |
| bb_perror_msg("%s, %s", intf, why); | |
| return EXIT_FAILURE; | |
| @@ -924,7 +924,7 @@ int top_main(int argc, char **argv) | |
| #if !ENABLE_FEATURE_USE_TERMIOS | |
| sleep(interval); | |
| #else | |
| - | if (poll(pfd, 1, interval * 1000) != 0) { |
| + | if (safe_poll(pfd, 1, interval * 1000) > 0) { |
| if (read(0, &c, 1) != 1) /* signal */ | |
| break; | |
| if (c == initial_settings.c_cc[VINTR]) | |
| @@ -665,7 +665,7 @@ static ssize_t ndelay_read(int fd, void *buf, size_t count) | |
| } | |
| /* Used for reading stdin */ | |
| - | static int buffer_pread(int fd, char *s, unsigned len) |
| + | static int buffer_pread(/*int fd, */char *s, unsigned len) |
| { | |
| unsigned now; | |
| struct pollfd input; | |
| @@ -709,7 +709,7 @@ static int buffer_pread(int fd, char *s, unsigned len) | |
| poll(&input, 1, i * 1000); | |
| sigprocmask(SIG_BLOCK, blocked_sigset, NULL); | |
| - | i = ndelay_read(fd, s, len); |
| + | i = ndelay_read(0, s, len); |
| if (i >= 0) | |
| break; | |
| if (errno == EINTR) | |
| @@ -909,7 +909,7 @@ int svlogd_main(int argc, char **argv) | |
| if (!np && !exitasap) { | |
| i = linemax - stdin_cnt; /* avail. bytes at tail */ | |
| if (i >= 128) { | |
| - | i = buffer_pread(0, lineptr + stdin_cnt, i); |
| + | i = buffer_pread(/*0, */lineptr + stdin_cnt, i); |
| if (i <= 0) /* EOF or error on stdin */ | |
| exitasap = 1; | |
| else { | |
| @@ -966,7 +966,7 @@ int svlogd_main(int argc, char **argv) | |
| /* read/write repeatedly until we see it */ | |
| while (ch != '\n') { | |
| /* lineptr is emptied now, safe to use as buffer */ | |
| - | stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax); |
| + | stdin_cnt = exitasap ? -1 : buffer_pread(/*0, */lineptr, linemax); |
| if (stdin_cnt <= 0) { /* EOF or error on stdin */ | |
| exitasap = 1; | |
| lineptr[0] = ch = '\n'; | |