aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-09-27 10:09:59 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-09-27 10:09:59 +0000
commit5d61e71c3a8ac3296afbfe9a014c62050c5a9234 (patch)
treee9ab2cd35d1f2d51b26a678551a0439b1719928b
parentc9dc2ac578278e86be248cc21e53081f7054da83 (diff)
downloadbusybox-w32-5d61e71c3a8ac3296afbfe9a014c62050c5a9234.tar.gz
busybox-w32-5d61e71c3a8ac3296afbfe9a014c62050c5a9234.tar.bz2
busybox-w32-5d61e71c3a8ac3296afbfe9a014c62050c5a9234.zip
introduce safe_poll (fixes a problem in top)
function old new delta safe_poll - 77 +77 svlogd_main 1470 1466 -4 zcip_main 1530 1524 -6 forkexec 1345 1338 -7 decode_format_string 795 788 -7 collect_blk 474 467 -7 buffer_pread 540 532 -8 tftp 1182 1172 -10 microcom_main 763 749 -14 arpping 441 424 -17 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 0/9 up/down: 77/-80) Total: -3 bytes text data bss dec hex filename 770162 1034 10404 781600 bed20 busybox_old 770158 1034 10404 781596 bed1c busybox_unstripped
-rw-r--r--editors/vi.c4
-rw-r--r--include/libbb.h8
-rw-r--r--libbb/Kbuild1
-rw-r--r--libbb/safe_poll.c34
-rw-r--r--libbb/safe_strncpy.c2
-rw-r--r--miscutils/microcom.c3
-rw-r--r--networking/httpd.c6
-rw-r--r--networking/tftp.c4
-rw-r--r--networking/traceroute.c2
-rw-r--r--networking/udhcp/arpping.c7
-rw-r--r--networking/zcip.c14
-rw-r--r--procps/top.c2
-rw-r--r--runit/svlogd.c8
13 files changed, 65 insertions, 30 deletions
diff --git a/editors/vi.c b/editors/vi.c
index f5df41636..1fa7c3a09 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -2139,7 +2139,7 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds
2139 2139
2140 pfd[0].fd = 0; 2140 pfd[0].fd = 0;
2141 pfd[0].events = POLLIN; 2141 pfd[0].events = POLLIN;
2142 return poll(pfd, 1, hund*10) > 0; 2142 return safe_poll(pfd, 1, hund*10) > 0;
2143} 2143}
2144 2144
2145#define readbuffer bb_common_bufsiz1 2145#define readbuffer bb_common_bufsiz1
@@ -2221,7 +2221,7 @@ static char readit(void) // read (maybe cursor) key from stdin
2221 pfd[0].events = POLLIN; 2221 pfd[0].events = POLLIN;
2222 // Wait 50 ms 2222 // Wait 50 ms
2223 // keep reading while there are input chars and room in buffer 2223 // keep reading while there are input chars and room in buffer
2224 while (poll(pfd, 1, 50) > 0 && n <= (MAX_LINELEN - 5)) { 2224 while (safe_poll(pfd, 1, 50) > 0 && n <= (MAX_LINELEN - 5)) {
2225 // read the rest of the ESC string 2225 // read the rest of the ESC string
2226 int r = read(0, readbuffer + n, MAX_LINELEN - n); 2226 int r = read(0, readbuffer + n, MAX_LINELEN - n);
2227 if (r > 0) 2227 if (r > 0)
diff --git a/include/libbb.h b/include/libbb.h
index 407b723b2..26a0f0d4a 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -451,8 +451,14 @@ extern FILE *fopen_or_warn(const char *filename, const char *mode);
451/* "Opens" stdin if filename is special, else just opens file: */ 451/* "Opens" stdin if filename is special, else just opens file: */
452extern FILE *fopen_or_warn_stdin(const char *filename); 452extern FILE *fopen_or_warn_stdin(const char *filename);
453 453
454/* Wrapper which restarts poll on EINTR or ENOMEM.
455 * On other errors complains [perror("poll")] and returns.
456 * Warning! May take (much) longer than timeout_ms to return!
457 * If this is a problem, use bare poll and open-code EINTR/ENOMEM handling */
458int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout_ms);
459
454/* Convert each alpha char in str to lower-case */ 460/* Convert each alpha char in str to lower-case */
455extern char* str_tolower(char *str); 461char* str_tolower(char *str);
456 462
457char *utoa(unsigned n); 463char *utoa(unsigned n);
458char *itoa(int n); 464char *itoa(int n);
diff --git a/libbb/Kbuild b/libbb/Kbuild
index 1800bde8f..55b3658b4 100644
--- a/libbb/Kbuild
+++ b/libbb/Kbuild
@@ -71,6 +71,7 @@ lib-y += recursive_action.o
71lib-y += remove_file.o 71lib-y += remove_file.o
72lib-y += restricted_shell.o 72lib-y += restricted_shell.o
73lib-y += run_shell.o 73lib-y += run_shell.o
74lib-y += safe_poll.o
74lib-y += safe_strncpy.o 75lib-y += safe_strncpy.o
75lib-y += safe_write.o 76lib-y += safe_write.o
76lib-y += setup_environment.o 77lib-y += setup_environment.o
diff --git a/libbb/safe_poll.c b/libbb/safe_poll.c
new file mode 100644
index 000000000..d2b773c36
--- /dev/null
+++ b/libbb/safe_poll.c
@@ -0,0 +1,34 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
5 * Copyright (C) 2007 by Denys Vlasenko <vda.linux@googlemail.com>
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
10#include "libbb.h"
11
12/* Wrapper which restarts poll on EINTR or ENOMEM.
13 * On other errors does perror("poll") and returns.
14 * Warning! May take longer than timeout_ms to return! */
15int safe_poll(struct pollfd *ufds, nfds_t nfds, int timeout)
16{
17 while (1) {
18 int n = poll(ufds, nfds, timeout);
19 if (n >= 0)
20 return n;
21 /* Make sure we inch towards completion */
22 if (timeout > 0)
23 timeout--;
24 /* E.g. strace causes poll to return this */
25 if (errno == EINTR)
26 continue;
27 /* Kernel is very low on memory. Retry. */
28 /* I doubt many callers would handle this correctly! */
29 if (errno == ENOMEM)
30 continue;
31 bb_perror_msg("poll");
32 return n;
33 }
34}
diff --git a/libbb/safe_strncpy.c b/libbb/safe_strncpy.c
index ebc7e28f3..cc425839f 100644
--- a/libbb/safe_strncpy.c
+++ b/libbb/safe_strncpy.c
@@ -10,7 +10,7 @@
10#include "libbb.h" 10#include "libbb.h"
11 11
12/* Like strncpy but make sure the resulting string is always 0 terminated. */ 12/* Like strncpy but make sure the resulting string is always 0 terminated. */
13char * safe_strncpy(char *dst, const char *src, size_t size) 13char *safe_strncpy(char *dst, const char *src, size_t size)
14{ 14{
15 if (!size) return dst; 15 if (!size) return dst;
16 dst[--size] = '\0'; 16 dst[--size] = '\0';
diff --git a/miscutils/microcom.c b/miscutils/microcom.c
index 59a91024e..5928569d5 100644
--- a/miscutils/microcom.c
+++ b/miscutils/microcom.c
@@ -105,8 +105,7 @@ int microcom_main(int argc, char **argv)
105 pfd[1].events = POLLIN; 105 pfd[1].events = POLLIN;
106 while (1) { 106 while (1) {
107 int i; 107 int i;
108 while (-1 == poll(pfd, 2, -1) && EINTR == errno) 108 safe_poll(pfd, 2, -1);
109 continue;
110 for (i = 0; i < 2; ++i) { 109 for (i = 0; i < 2; ++i) {
111 if (pfd[i].revents & POLLIN) { 110 if (pfd[i].revents & POLLIN) {
112 len = read(pfd[i].fd, bb_common_bufsiz1, COMMON_BUFSIZE); 111 len = read(pfd[i].fd, bb_common_bufsiz1, COMMON_BUFSIZE);
diff --git a/networking/httpd.c b/networking/httpd.c
index cedec800f..92a07107d 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1073,13 +1073,9 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1073 } 1073 }
1074 1074
1075 /* Now wait on the set of sockets */ 1075 /* Now wait on the set of sockets */
1076 count = poll(pfd, 3, -1); 1076 count = safe_poll(pfd, 3, -1);
1077 if (count <= 0) { 1077 if (count <= 0) {
1078#if 0 1078#if 0
1079 if (errno == EINTR)
1080 continue;
1081#endif
1082#if 0
1083 if (waitpid(pid, &status, WNOHANG) <= 0) { 1079 if (waitpid(pid, &status, WNOHANG) <= 0) {
1084 /* Weird. CGI didn't exit and no fd's 1080 /* Weird. CGI didn't exit and no fd's
1085 * are ready, yet poll returned?! */ 1081 * are ready, yet poll returned?! */
diff --git a/networking/tftp.c b/networking/tftp.c
index ac3a86afb..59f53ae4a 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -225,7 +225,7 @@ static int tftp( USE_GETPUT(const int cmd,)
225 /* Receive packet */ 225 /* Receive packet */
226 /*pfd[0].fd = socketfd;*/ 226 /*pfd[0].fd = socketfd;*/
227 pfd[0].events = POLLIN; 227 pfd[0].events = POLLIN;
228 switch (poll(pfd, 1, waittime_ms)) { 228 switch (safe_poll(pfd, 1, waittime_ms)) {
229 unsigned from_port; 229 unsigned from_port;
230 case 1: 230 case 1:
231 from->len = peer_lsa->len; 231 from->len = peer_lsa->len;
@@ -262,7 +262,7 @@ static int tftp( USE_GETPUT(const int cmd,)
262 262
263 goto send_again; /* resend last sent pkt */ 263 goto send_again; /* resend last sent pkt */
264 default: 264 default:
265 bb_perror_msg("poll"); 265 /*bb_perror_msg("poll"); - done in safe_poll */
266 goto ret; 266 goto ret;
267 } 267 }
268 process_pkt: 268 process_pkt:
diff --git a/networking/traceroute.c b/networking/traceroute.c
index 21921e56d..2d09c7197 100644
--- a/networking/traceroute.c
+++ b/networking/traceroute.c
@@ -543,7 +543,7 @@ wait_for_reply(int sock, struct sockaddr_in *fromp)
543 543
544 pfd[0].fd = sock; 544 pfd[0].fd = sock;
545 pfd[0].events = POLLIN; 545 pfd[0].events = POLLIN;
546 if (poll(pfd, 1, waittime * 1000) > 0) 546 if (safe_poll(pfd, 1, waittime * 1000) > 0)
547 cc = recvfrom(sock, packet, sizeof(packet), 0, 547 cc = recvfrom(sock, packet, sizeof(packet), 0,
548 (struct sockaddr *)fromp, &fromlen); 548 (struct sockaddr *)fromp, &fromlen);
549 return cc; 549 return cc;
diff --git a/networking/udhcp/arpping.c b/networking/udhcp/arpping.c
index 33518077b..7b702d8f3 100644
--- a/networking/udhcp/arpping.c
+++ b/networking/udhcp/arpping.c
@@ -81,12 +81,9 @@ int arpping(uint32_t test_ip, uint32_t from_ip, uint8_t *from_mac, const char *i
81 unsigned prevTime = monotonic_us(); 81 unsigned prevTime = monotonic_us();
82 82
83 pfd[0].events = POLLIN; 83 pfd[0].events = POLLIN;
84 r = poll(pfd, 1, timeout_ms); 84 r = safe_poll(pfd, 1, timeout_ms);
85 if (r < 0) { 85 if (r < 0) {
86 if (errno != EINTR) { 86 break;
87 bb_perror_msg("poll");
88 break;
89 }
90 } else if (r) { 87 } else if (r) {
91 if (read(s, &arp, sizeof(arp)) < 0) 88 if (read(s, &arp, sizeof(arp)) < 0)
92 break; 89 break;
diff --git a/networking/zcip.c b/networking/zcip.c
index 2f0b5a7fb..63846ebef 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -300,7 +300,12 @@ int zcip_main(int argc, char **argv)
300 300
301 VDBG("...wait %d %s nprobes=%u, nclaims=%u\n", 301 VDBG("...wait %d %s nprobes=%u, nclaims=%u\n",
302 timeout_ms, intf, nprobes, nclaims); 302 timeout_ms, intf, nprobes, nclaims);
303 switch (poll(fds, 1, timeout_ms)) { 303
304 switch (safe_poll(fds, 1, timeout_ms)) {
305
306 default:
307 /*bb_perror_msg("poll"); - done in safe_poll */
308 return EXIT_FAILURE;
304 309
305 // timeout 310 // timeout
306 case 0: 311 case 0:
@@ -388,6 +393,7 @@ int zcip_main(int argc, char **argv)
388 break; 393 break;
389 } // switch (state) 394 } // switch (state)
390 break; // case 0 (timeout) 395 break; // case 0 (timeout)
396
391 // packets arriving 397 // packets arriving
392 case 1: 398 case 1:
393 // We need to adjust the timeout in case we didn't receive 399 // We need to adjust the timeout in case we didn't receive
@@ -519,13 +525,9 @@ int zcip_main(int argc, char **argv)
519 nclaims = 0; 525 nclaims = 0;
520 break; 526 break;
521 } // switch state 527 } // switch state
522
523 break; // case 1 (packets arriving) 528 break; // case 1 (packets arriving)
524 default:
525 why = "poll";
526 goto bad;
527 } // switch poll 529 } // switch poll
528 } 530 } // while (1)
529 bad: 531 bad:
530 bb_perror_msg("%s, %s", intf, why); 532 bb_perror_msg("%s, %s", intf, why);
531 return EXIT_FAILURE; 533 return EXIT_FAILURE;
diff --git a/procps/top.c b/procps/top.c
index ac3b7e5a2..e55cecccb 100644
--- a/procps/top.c
+++ b/procps/top.c
@@ -924,7 +924,7 @@ int top_main(int argc, char **argv)
924#if !ENABLE_FEATURE_USE_TERMIOS 924#if !ENABLE_FEATURE_USE_TERMIOS
925 sleep(interval); 925 sleep(interval);
926#else 926#else
927 if (poll(pfd, 1, interval * 1000) != 0) { 927 if (safe_poll(pfd, 1, interval * 1000) > 0) {
928 if (read(0, &c, 1) != 1) /* signal */ 928 if (read(0, &c, 1) != 1) /* signal */
929 break; 929 break;
930 if (c == initial_settings.c_cc[VINTR]) 930 if (c == initial_settings.c_cc[VINTR])
diff --git a/runit/svlogd.c b/runit/svlogd.c
index 6c8747e96..b5eed15ab 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -665,7 +665,7 @@ static ssize_t ndelay_read(int fd, void *buf, size_t count)
665} 665}
666 666
667/* Used for reading stdin */ 667/* Used for reading stdin */
668static int buffer_pread(int fd, char *s, unsigned len) 668static int buffer_pread(/*int fd, */char *s, unsigned len)
669{ 669{
670 unsigned now; 670 unsigned now;
671 struct pollfd input; 671 struct pollfd input;
@@ -709,7 +709,7 @@ static int buffer_pread(int fd, char *s, unsigned len)
709 poll(&input, 1, i * 1000); 709 poll(&input, 1, i * 1000);
710 sigprocmask(SIG_BLOCK, blocked_sigset, NULL); 710 sigprocmask(SIG_BLOCK, blocked_sigset, NULL);
711 711
712 i = ndelay_read(fd, s, len); 712 i = ndelay_read(0, s, len);
713 if (i >= 0) 713 if (i >= 0)
714 break; 714 break;
715 if (errno == EINTR) 715 if (errno == EINTR)
@@ -909,7 +909,7 @@ int svlogd_main(int argc, char **argv)
909 if (!np && !exitasap) { 909 if (!np && !exitasap) {
910 i = linemax - stdin_cnt; /* avail. bytes at tail */ 910 i = linemax - stdin_cnt; /* avail. bytes at tail */
911 if (i >= 128) { 911 if (i >= 128) {
912 i = buffer_pread(0, lineptr + stdin_cnt, i); 912 i = buffer_pread(/*0, */lineptr + stdin_cnt, i);
913 if (i <= 0) /* EOF or error on stdin */ 913 if (i <= 0) /* EOF or error on stdin */
914 exitasap = 1; 914 exitasap = 1;
915 else { 915 else {
@@ -966,7 +966,7 @@ int svlogd_main(int argc, char **argv)
966 /* read/write repeatedly until we see it */ 966 /* read/write repeatedly until we see it */
967 while (ch != '\n') { 967 while (ch != '\n') {
968 /* lineptr is emptied now, safe to use as buffer */ 968 /* lineptr is emptied now, safe to use as buffer */
969 stdin_cnt = exitasap ? -1 : buffer_pread(0, lineptr, linemax); 969 stdin_cnt = exitasap ? -1 : buffer_pread(/*0, */lineptr, linemax);
970 if (stdin_cnt <= 0) { /* EOF or error on stdin */ 970 if (stdin_cnt <= 0) { /* EOF or error on stdin */
971 exitasap = 1; 971 exitasap = 1;
972 lineptr[0] = ch = '\n'; 972 lineptr[0] = ch = '\n';