aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-01-02 19:55:04 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-01-02 19:55:04 +0000
commitfb0eba706cccd510d99c4c5339a76dd15bc8a628 (patch)
tree45122b93a1a5d628e4aa146251e34397094de817
parent27963980dbe1262fd6c447fc7d06839aea0861bc (diff)
downloadbusybox-w32-fb0eba706cccd510d99c4c5339a76dd15bc8a628.tar.gz
busybox-w32-fb0eba706cccd510d99c4c5339a76dd15bc8a628.tar.bz2
busybox-w32-fb0eba706cccd510d99c4c5339a76dd15bc8a628.zip
libbb: introduce and use safe_waitpid (loops in EINTR)
*: use more approproate (shorter) versions of wait() function old new delta safe_waitpid - 48 +48 wait_any_nohang - 17 +17 send_tree 365 369 +4 processorstop 432 435 +3 text_yank 110 108 -2 make_human_readable_str 202 200 -2 crond_main 1368 1366 -2 handle_sigchld 49 43 -6 reapchild 166 159 -7 custom 260 250 -10 checkscript 191 177 -14 wait_nohang 17 - -17 wait_pid 43 - -43 ------------------------------------------------------------------------------ (add/remove: 2/2 grow/shrink: 2/7 up/down: 72/-103) Total: -31 bytes
-rw-r--r--archival/tar.c4
-rw-r--r--include/libbb.h4
-rw-r--r--init/init.c26
-rw-r--r--ipsvd/tcpudp.c2
-rw-r--r--libbb/vfork_daemon_rexec.c37
-rw-r--r--miscutils/crond.c2
-rw-r--r--networking/httpd.c2
-rw-r--r--networking/ifupdown.c4
-rw-r--r--networking/inetd.c2
-rw-r--r--networking/telnetd.c2
-rw-r--r--networking/udhcp/script.c2
-rw-r--r--runit/runsv.c5
-rw-r--r--runit/runsvdir.c2
-rw-r--r--runit/sv.c3
-rw-r--r--runit/svlogd.c4
-rw-r--r--shell/ash.c2
-rw-r--r--shell/hush.c1
-rw-r--r--shell/msh.c2
18 files changed, 51 insertions, 55 deletions
diff --git a/archival/tar.c b/archival/tar.c
index 5b19093e8..64975c428 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -610,7 +610,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
610 610
611 if (gzipPid) { 611 if (gzipPid) {
612 int status; 612 int status;
613 if (waitpid(gzipPid, &status, 0) == -1) 613 if (safe_waitpid(gzipPid, &status, 0) == -1)
614 bb_perror_msg("waitpid"); 614 bb_perror_msg("waitpid");
615 else if (!WIFEXITED(status) || WEXITSTATUS(status)) 615 else if (!WIFEXITED(status) || WEXITSTATUS(status))
616 /* gzip was killed or has exited with nonzero! */ 616 /* gzip was killed or has exited with nonzero! */
@@ -688,7 +688,7 @@ static void handle_SIGCHLD(int status)
688 /* Actually, 'status' is a signo. We reuse it for other needs */ 688 /* Actually, 'status' is a signo. We reuse it for other needs */
689 689
690 /* Wait for any child without blocking */ 690 /* Wait for any child without blocking */
691 if (waitpid(-1, &status, WNOHANG) < 0) 691 if (wait_any_nohang(&status) < 0)
692 /* wait failed?! I'm confused... */ 692 /* wait failed?! I'm confused... */
693 return; 693 return;
694 694
diff --git a/include/libbb.h b/include/libbb.h
index f35f85c33..fef8fe2e0 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -587,9 +587,9 @@ pid_t xspawn(char **argv);
587 * if (rc < 0) bb_perror_msg("%s", argv[0]); 587 * if (rc < 0) bb_perror_msg("%s", argv[0]);
588 * if (rc > 0) bb_error_msg("exit code: %d", rc); 588 * if (rc > 0) bb_error_msg("exit code: %d", rc);
589 */ 589 */
590int safe_waitpid(int pid, int *wstat, int options);
590int wait4pid(int pid); 591int wait4pid(int pid);
591int wait_pid(int *wstat, int pid); 592int wait_any_nohang(int *wstat);
592int wait_nohang(int *wstat);
593#define wait_crashed(w) ((w) & 127) 593#define wait_crashed(w) ((w) & 127)
594#define wait_exitcode(w) ((w) >> 8) 594#define wait_exitcode(w) ((w) >> 8)
595#define wait_stopsig(w) ((w) >> 8) 595#define wait_stopsig(w) ((w) >> 8)
diff --git a/init/init.c b/init/init.c
index 51125f348..68a59d88e 100644
--- a/init/init.c
+++ b/init/init.c
@@ -95,9 +95,14 @@ static const char *const environment[] = {
95 95
96/* Function prototypes */ 96/* Function prototypes */
97static void delete_init_action(struct init_action *a); 97static void delete_init_action(struct init_action *a);
98static int waitfor(pid_t pid);
99static void halt_reboot_pwoff(int sig) ATTRIBUTE_NORETURN; 98static void halt_reboot_pwoff(int sig) ATTRIBUTE_NORETURN;
100 99
100/* TODO: move to libbb? */
101static int waitfor(pid_t runpid)
102{
103 return safe_waitpid(runpid, NULL, 0);
104}
105
101static void loop_forever(void) ATTRIBUTE_NORETURN; 106static void loop_forever(void) ATTRIBUTE_NORETURN;
102static void loop_forever(void) 107static void loop_forever(void)
103{ 108{
@@ -465,19 +470,6 @@ static pid_t run(const struct init_action *a)
465 _exit(-1); 470 _exit(-1);
466} 471}
467 472
468static int waitfor(pid_t runpid)
469{
470 int status, wpid;
471
472 while (1) {
473 wpid = waitpid(runpid, &status, 0);
474 if (wpid == -1 && errno == EINTR)
475 continue;
476 break;
477 }
478 return wpid;
479}
480
481/* Run all commands of a particular type */ 473/* Run all commands of a particular type */
482static void run_actions(int action) 474static void run_actions(int action)
483{ 475{
@@ -520,7 +512,7 @@ static void init_reboot(unsigned long magic)
520 reboot(magic); 512 reboot(magic);
521 _exit(0); 513 _exit(0);
522 } 514 }
523 waitpid(pid, NULL, 0); 515 waitfor(pid);
524} 516}
525 517
526static void kill_all_processes(void) 518static void kill_all_processes(void)
@@ -980,7 +972,7 @@ int init_main(int argc, char **argv)
980 /* Don't consume all CPU time -- sleep a bit */ 972 /* Don't consume all CPU time -- sleep a bit */
981 sleep(1); 973 sleep(1);
982 974
983 /* Wait for a child process to exit */ 975 /* Wait for any child process to exit */
984 wpid = wait(NULL); 976 wpid = wait(NULL);
985 while (wpid > 0) { 977 while (wpid > 0) {
986 /* Find out who died and clean up their corpse */ 978 /* Find out who died and clean up their corpse */
@@ -995,7 +987,7 @@ int init_main(int argc, char **argv)
995 } 987 }
996 } 988 }
997 /* see if anyone else is waiting to be reaped */ 989 /* see if anyone else is waiting to be reaped */
998 wpid = waitpid(-1, NULL, WNOHANG); 990 wpid = wait_any_nohang(NULL);
999 } 991 }
1000 } 992 }
1001} 993}
diff --git a/ipsvd/tcpudp.c b/ipsvd/tcpudp.c
index fc29274d2..6187eb985 100644
--- a/ipsvd/tcpudp.c
+++ b/ipsvd/tcpudp.c
@@ -121,7 +121,7 @@ static void sig_child_handler(int sig)
121 int wstat; 121 int wstat;
122 int pid; 122 int pid;
123 123
124 while ((pid = wait_nohang(&wstat)) > 0) { 124 while ((pid = wait_any_nohang(&wstat)) > 0) {
125 if (max_per_host) 125 if (max_per_host)
126 ipsvd_perhost_remove(pid); 126 ipsvd_perhost_remove(pid);
127 if (cnum) 127 if (cnum)
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index d6e233ac3..4e6ecde67 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -66,6 +66,21 @@ pid_t xspawn(char **argv)
66 return pid; 66 return pid;
67} 67}
68 68
69int safe_waitpid(int pid, int *wstat, int options)
70{
71 int r;
72
73 do
74 r = waitpid(pid, wstat, options);
75 while ((r == -1) && (errno == EINTR));
76 return r;
77}
78
79int wait_any_nohang(int *wstat)
80{
81 return safe_waitpid(-1, wstat, WNOHANG);
82}
83
69// Wait for the specified child PID to exit, returning child's error return. 84// Wait for the specified child PID to exit, returning child's error return.
70int wait4pid(int pid) 85int wait4pid(int pid)
71{ 86{
@@ -76,28 +91,18 @@ int wait4pid(int pid)
76 /* we expect errno to be already set from failed [v]fork/exec */ 91 /* we expect errno to be already set from failed [v]fork/exec */
77 return -1; 92 return -1;
78 } 93 }
79 if (waitpid(pid, &status, 0) == -1) 94 if (safe_waitpid(pid, &status, 0) == -1)
80 return -1; 95 return -1;
81 if (WIFEXITED(status)) 96 if (WIFEXITED(status))
82 return WEXITSTATUS(status); 97 return WEXITSTATUS(status);
83 if (WIFSIGNALED(status)) 98 if (WIFSIGNALED(status))
84 return WTERMSIG(status) + 1000; 99 return WTERMSIG(status) + 1000;
85 return 0; 100 return 0;
86} 101 if (WIFEXITED(status))
87 102 return WEXITSTATUS(status);
88int wait_nohang(int *wstat) 103 if (WIFSIGNALED(status))
89{ 104 return WTERMSIG(status) + 1000;
90 return waitpid(-1, wstat, WNOHANG); 105 return 0;
91}
92
93int wait_pid(int *wstat, int pid)
94{
95 int r;
96
97 do
98 r = waitpid(pid, wstat, 0);
99 while ((r == -1) && (errno == EINTR));
100 return r;
101} 106}
102 107
103#if ENABLE_FEATURE_PREFER_APPLETS 108#if ENABLE_FEATURE_PREFER_APPLETS
diff --git a/miscutils/crond.c b/miscutils/crond.c
index 8ee7e5837..6056cb065 100644
--- a/miscutils/crond.c
+++ b/miscutils/crond.c
@@ -756,7 +756,7 @@ static int CheckJobs(void)
756 for (line = file->cf_LineBase; line; line = line->cl_Next) { 756 for (line = file->cf_LineBase; line; line = line->cl_Next) {
757 if (line->cl_Pid > 0) { 757 if (line->cl_Pid > 0) {
758 int status; 758 int status;
759 int r = wait4(line->cl_Pid, &status, WNOHANG, NULL); 759 int r = waitpid(line->cl_Pid, &status, WNOHANG);
760 760
761 if (r < 0 || r == line->cl_Pid) { 761 if (r < 0 || r == line->cl_Pid) {
762 EndJob(file->cf_User, line); 762 EndJob(file->cf_User, line);
diff --git a/networking/httpd.c b/networking/httpd.c
index 87dc4b7da..72949755a 100644
--- a/networking/httpd.c
+++ b/networking/httpd.c
@@ -1152,7 +1152,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
1152 count = safe_poll(pfd, 3, -1); 1152 count = safe_poll(pfd, 3, -1);
1153 if (count <= 0) { 1153 if (count <= 0) {
1154#if 0 1154#if 0
1155 if (waitpid(pid, &status, WNOHANG) <= 0) { 1155 if (safe_waitpid(pid, &status, WNOHANG) <= 0) {
1156 /* Weird. CGI didn't exit and no fd's 1156 /* Weird. CGI didn't exit and no fd's
1157 * are ready, yet poll returned?! */ 1157 * are ready, yet poll returned?! */
1158 continue; 1158 continue;
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 31911cd21..68ea01a67 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -944,7 +944,7 @@ static int doit(char *str)
944 execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ); 944 execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ);
945 exit(127); 945 exit(127);
946 } 946 }
947 waitpid(child, &status, 0); 947 safe_waitpid(child, &status, 0);
948 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 948 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
949 return 0; 949 return 0;
950 } 950 }
@@ -1068,7 +1068,7 @@ static char *run_mapping(char *physical, struct mapping_defn_t * map)
1068 fprintf(in, "%s\n", map->mapping[i]); 1068 fprintf(in, "%s\n", map->mapping[i]);
1069 } 1069 }
1070 fclose(in); 1070 fclose(in);
1071 waitpid(pid, &status, 0); 1071 safe_waitpid(pid, &status, 0);
1072 1072
1073 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 1073 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
1074 /* If the mapping script exited successfully, try to 1074 /* If the mapping script exited successfully, try to
diff --git a/networking/inetd.c b/networking/inetd.c
index a9c9397f5..d643dc6e0 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1161,7 +1161,7 @@ static void reapchild(int sig ATTRIBUTE_UNUSED)
1161 servtab_t *sep; 1161 servtab_t *sep;
1162 1162
1163 for (;;) { 1163 for (;;) {
1164 pid = wait3(&status, WNOHANG, NULL); 1164 pid = wait_any_nohang(&status);
1165 if (pid <= 0) 1165 if (pid <= 0)
1166 break; 1166 break;
1167 for (sep = servtab; sep; sep = sep->se_next) 1167 for (sep = servtab; sep; sep = sep->se_next)
diff --git a/networking/telnetd.c b/networking/telnetd.c
index 108bbf44f..0201d2636 100644
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -394,7 +394,7 @@ static void handle_sigchld(int sig)
394 394
395 /* Looping: more than one child may have exited */ 395 /* Looping: more than one child may have exited */
396 while (1) { 396 while (1) {
397 pid = waitpid(-1, NULL, WNOHANG); 397 pid = wait_any_nohang(NULL);
398 if (pid <= 0) 398 if (pid <= 0)
399 break; 399 break;
400 ts = sessions; 400 ts = sessions;
diff --git a/networking/udhcp/script.c b/networking/udhcp/script.c
index 8a188988e..71f033328 100644
--- a/networking/udhcp/script.c
+++ b/networking/udhcp/script.c
@@ -232,7 +232,7 @@ void udhcp_run_script(struct dhcpMessage *packet, const char *name)
232 name, NULL, envp); 232 name, NULL, envp);
233 bb_perror_msg_and_die("script %s failed", client_config.script); 233 bb_perror_msg_and_die("script %s failed", client_config.script);
234 } 234 }
235 waitpid(pid, NULL, 0); 235 safe_waitpid(pid, NULL, 0);
236 for (curr = envp; *curr; curr++) 236 for (curr = envp; *curr; curr++)
237 free(*curr); 237 free(*curr);
238 free(envp); 238 free(envp);
diff --git a/runit/runsv.c b/runit/runsv.c
index 8c5a4d4ea..84f5193f5 100644
--- a/runit/runsv.c
+++ b/runit/runsv.c
@@ -282,8 +282,7 @@ static unsigned custom(struct svdir *s, char c)
282 execve(a, prog, environ); 282 execve(a, prog, environ);
283 fatal_cannot("run control/?"); 283 fatal_cannot("run control/?");
284 } 284 }
285 while (wait_pid(&w, pid) == -1) { 285 while (safe_waitpid(pid, &w, 0) == -1) {
286 if (errno == EINTR) continue;
287 warn_cannot("wait for child control/?"); 286 warn_cannot("wait for child control/?");
288 return 0; 287 return 0;
289 } 288 }
@@ -593,7 +592,7 @@ int runsv_main(int argc, char **argv)
593 int child; 592 int child;
594 int wstat; 593 int wstat;
595 594
596 child = wait_nohang(&wstat); 595 child = wait_any_nohang(&wstat);
597 if (!child) 596 if (!child)
598 break; 597 break;
599 if ((child == -1) && (errno != EINTR)) 598 if ((child == -1) && (errno != EINTR))
diff --git a/runit/runsvdir.c b/runit/runsvdir.c
index 9e98ca6f8..838490376 100644
--- a/runit/runsvdir.c
+++ b/runit/runsvdir.c
@@ -252,7 +252,7 @@ int runsvdir_main(int argc, char **argv)
252 for (;;) { 252 for (;;) {
253 /* collect children */ 253 /* collect children */
254 for (;;) { 254 for (;;) {
255 pid = wait_nohang(&wstat); 255 pid = wait_any_nohang(&wstat);
256 if (pid <= 0) 256 if (pid <= 0)
257 break; 257 break;
258 for (i = 0; i < svnum; i++) { 258 for (i = 0; i < svnum; i++) {
diff --git a/runit/sv.c b/runit/sv.c
index e31adffed..a89e24439 100644
--- a/runit/sv.c
+++ b/runit/sv.c
@@ -333,8 +333,7 @@ static int checkscript(void)
333 bb_perror_msg(WARN"cannot %s child %s/check", "run", *service); 333 bb_perror_msg(WARN"cannot %s child %s/check", "run", *service);
334 return 0; 334 return 0;
335 } 335 }
336 while (wait_pid(&w, pid) == -1) { 336 while (safe_waitpid(pid, &w, 0) == -1) {
337 if (errno == EINTR) continue;
338 bb_perror_msg(WARN"cannot %s child %s/check", "wait for", *service); 337 bb_perror_msg(WARN"cannot %s child %s/check", "wait for", *service);
339 return 0; 338 return 0;
340 } 339 }
diff --git a/runit/svlogd.c b/runit/svlogd.c
index 2dc8cb987..1d679c972 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -265,7 +265,7 @@ static unsigned processorstop(struct logdir *ld)
265 265
266 if (ld->ppid) { 266 if (ld->ppid) {
267 sig_unblock(SIGHUP); 267 sig_unblock(SIGHUP);
268 while (wait_pid(&wstat, ld->ppid) == -1) 268 while (safe_waitpid(ld->ppid, &wstat, 0) == -1)
269 pause2cannot("wait for processor", ld->name); 269 pause2cannot("wait for processor", ld->name);
270 sig_block(SIGHUP); 270 sig_block(SIGHUP);
271 ld->ppid = 0; 271 ld->ppid = 0;
@@ -794,7 +794,7 @@ static void sig_child_handler(int sig_no)
794 794
795 if (verbose) 795 if (verbose)
796 bb_error_msg(INFO"sig%s received", "child"); 796 bb_error_msg(INFO"sig%s received", "child");
797 while ((pid = wait_nohang(&wstat)) > 0) { 797 while ((pid = wait_any_nohang(&wstat)) > 0) {
798 for (l = 0; l < dirn; ++l) { 798 for (l = 0; l < dirn; ++l) {
799 if (dir[l].ppid == pid) { 799 if (dir[l].ppid == pid) {
800 dir[l].ppid = 0; 800 dir[l].ppid = 0;
diff --git a/shell/ash.c b/shell/ash.c
index a5b19c863..96563bf06 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -3768,7 +3768,7 @@ waitproc(int block, int *status)
3768#endif 3768#endif
3769 if (block == 0) 3769 if (block == 0)
3770 flags |= WNOHANG; 3770 flags |= WNOHANG;
3771 return wait3(status, flags, (struct rusage *)NULL); 3771 return waitpid(-1, status, flags); // safe_waitpid?
3772} 3772}
3773 3773
3774/* 3774/*
diff --git a/shell/hush.c b/shell/hush.c
index cb2c3e98e..b08fe10b6 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1649,6 +1649,7 @@ static int checkjobs(struct pipe* fg_pipe)
1649// + killall -STOP cat 1649// + killall -STOP cat
1650 1650
1651 wait_more: 1651 wait_more:
1652// TODO: safe_waitpid?
1652 while ((childpid = waitpid(-1, &status, attributes)) > 0) { 1653 while ((childpid = waitpid(-1, &status, attributes)) > 0) {
1653 const int dead = WIFEXITED(status) || WIFSIGNALED(status); 1654 const int dead = WIFEXITED(status) || WIFSIGNALED(status);
1654 1655
diff --git a/shell/msh.c b/shell/msh.c
index 9edf793ab..9e9b798a1 100644
--- a/shell/msh.c
+++ b/shell/msh.c
@@ -4162,7 +4162,7 @@ static int grave(int quoted)
4162 return 0; 4162 return 0;
4163 } 4163 }
4164 if (i != 0) { 4164 if (i != 0) {
4165 waitpid(i, NULL, 0); 4165 waitpid(i, NULL, 0); // safe_waitpid?
4166 global_env.iop->argp->aword = ++cp; 4166 global_env.iop->argp->aword = ++cp;
4167 close(pf[1]); 4167 close(pf[1]);
4168 PUSHIO(afile, remap(pf[0]), 4168 PUSHIO(afile, remap(pf[0]),