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
This commit is contained in:
Denis Vlasenko 2008-01-02 19:55:04 +00:00
parent 27963980db
commit fb0eba706c
18 changed files with 51 additions and 55 deletions

View File

@ -610,7 +610,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag,
if (gzipPid) { if (gzipPid) {
int status; int status;
if (waitpid(gzipPid, &status, 0) == -1) if (safe_waitpid(gzipPid, &status, 0) == -1)
bb_perror_msg("waitpid"); bb_perror_msg("waitpid");
else if (!WIFEXITED(status) || WEXITSTATUS(status)) else if (!WIFEXITED(status) || WEXITSTATUS(status))
/* gzip was killed or has exited with nonzero! */ /* gzip was killed or has exited with nonzero! */
@ -688,7 +688,7 @@ static void handle_SIGCHLD(int status)
/* Actually, 'status' is a signo. We reuse it for other needs */ /* Actually, 'status' is a signo. We reuse it for other needs */
/* Wait for any child without blocking */ /* Wait for any child without blocking */
if (waitpid(-1, &status, WNOHANG) < 0) if (wait_any_nohang(&status) < 0)
/* wait failed?! I'm confused... */ /* wait failed?! I'm confused... */
return; return;

View File

@ -587,9 +587,9 @@ pid_t xspawn(char **argv);
* if (rc < 0) bb_perror_msg("%s", argv[0]); * if (rc < 0) bb_perror_msg("%s", argv[0]);
* if (rc > 0) bb_error_msg("exit code: %d", rc); * if (rc > 0) bb_error_msg("exit code: %d", rc);
*/ */
int safe_waitpid(int pid, int *wstat, int options);
int wait4pid(int pid); int wait4pid(int pid);
int wait_pid(int *wstat, int pid); int wait_any_nohang(int *wstat);
int wait_nohang(int *wstat);
#define wait_crashed(w) ((w) & 127) #define wait_crashed(w) ((w) & 127)
#define wait_exitcode(w) ((w) >> 8) #define wait_exitcode(w) ((w) >> 8)
#define wait_stopsig(w) ((w) >> 8) #define wait_stopsig(w) ((w) >> 8)

View File

@ -95,9 +95,14 @@ static const char *const environment[] = {
/* Function prototypes */ /* Function prototypes */
static void delete_init_action(struct init_action *a); static void delete_init_action(struct init_action *a);
static int waitfor(pid_t pid);
static void halt_reboot_pwoff(int sig) ATTRIBUTE_NORETURN; static void halt_reboot_pwoff(int sig) ATTRIBUTE_NORETURN;
/* TODO: move to libbb? */
static int waitfor(pid_t runpid)
{
return safe_waitpid(runpid, NULL, 0);
}
static void loop_forever(void) ATTRIBUTE_NORETURN; static void loop_forever(void) ATTRIBUTE_NORETURN;
static void loop_forever(void) static void loop_forever(void)
{ {
@ -465,19 +470,6 @@ static pid_t run(const struct init_action *a)
_exit(-1); _exit(-1);
} }
static int waitfor(pid_t runpid)
{
int status, wpid;
while (1) {
wpid = waitpid(runpid, &status, 0);
if (wpid == -1 && errno == EINTR)
continue;
break;
}
return wpid;
}
/* Run all commands of a particular type */ /* Run all commands of a particular type */
static void run_actions(int action) static void run_actions(int action)
{ {
@ -520,7 +512,7 @@ static void init_reboot(unsigned long magic)
reboot(magic); reboot(magic);
_exit(0); _exit(0);
} }
waitpid(pid, NULL, 0); waitfor(pid);
} }
static void kill_all_processes(void) static void kill_all_processes(void)
@ -980,7 +972,7 @@ int init_main(int argc, char **argv)
/* Don't consume all CPU time -- sleep a bit */ /* Don't consume all CPU time -- sleep a bit */
sleep(1); sleep(1);
/* Wait for a child process to exit */ /* Wait for any child process to exit */
wpid = wait(NULL); wpid = wait(NULL);
while (wpid > 0) { while (wpid > 0) {
/* Find out who died and clean up their corpse */ /* Find out who died and clean up their corpse */
@ -995,7 +987,7 @@ int init_main(int argc, char **argv)
} }
} }
/* see if anyone else is waiting to be reaped */ /* see if anyone else is waiting to be reaped */
wpid = waitpid(-1, NULL, WNOHANG); wpid = wait_any_nohang(NULL);
} }
} }
} }

View File

@ -121,7 +121,7 @@ static void sig_child_handler(int sig)
int wstat; int wstat;
int pid; int pid;
while ((pid = wait_nohang(&wstat)) > 0) { while ((pid = wait_any_nohang(&wstat)) > 0) {
if (max_per_host) if (max_per_host)
ipsvd_perhost_remove(pid); ipsvd_perhost_remove(pid);
if (cnum) if (cnum)

View File

@ -66,6 +66,21 @@ pid_t xspawn(char **argv)
return pid; return pid;
} }
int safe_waitpid(int pid, int *wstat, int options)
{
int r;
do
r = waitpid(pid, wstat, options);
while ((r == -1) && (errno == EINTR));
return r;
}
int wait_any_nohang(int *wstat)
{
return safe_waitpid(-1, wstat, WNOHANG);
}
// Wait for the specified child PID to exit, returning child's error return. // Wait for the specified child PID to exit, returning child's error return.
int wait4pid(int pid) int wait4pid(int pid)
{ {
@ -76,28 +91,18 @@ int wait4pid(int pid)
/* we expect errno to be already set from failed [v]fork/exec */ /* we expect errno to be already set from failed [v]fork/exec */
return -1; return -1;
} }
if (waitpid(pid, &status, 0) == -1) if (safe_waitpid(pid, &status, 0) == -1)
return -1; return -1;
if (WIFEXITED(status)) if (WIFEXITED(status))
return WEXITSTATUS(status); return WEXITSTATUS(status);
if (WIFSIGNALED(status)) if (WIFSIGNALED(status))
return WTERMSIG(status) + 1000; return WTERMSIG(status) + 1000;
return 0; return 0;
} if (WIFEXITED(status))
return WEXITSTATUS(status);
int wait_nohang(int *wstat) if (WIFSIGNALED(status))
{ return WTERMSIG(status) + 1000;
return waitpid(-1, wstat, WNOHANG); return 0;
}
int wait_pid(int *wstat, int pid)
{
int r;
do
r = waitpid(pid, wstat, 0);
while ((r == -1) && (errno == EINTR));
return r;
} }
#if ENABLE_FEATURE_PREFER_APPLETS #if ENABLE_FEATURE_PREFER_APPLETS

View File

@ -756,7 +756,7 @@ static int CheckJobs(void)
for (line = file->cf_LineBase; line; line = line->cl_Next) { for (line = file->cf_LineBase; line; line = line->cl_Next) {
if (line->cl_Pid > 0) { if (line->cl_Pid > 0) {
int status; int status;
int r = wait4(line->cl_Pid, &status, WNOHANG, NULL); int r = waitpid(line->cl_Pid, &status, WNOHANG);
if (r < 0 || r == line->cl_Pid) { if (r < 0 || r == line->cl_Pid) {
EndJob(file->cf_User, line); EndJob(file->cf_User, line);

View File

@ -1152,7 +1152,7 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
count = safe_poll(pfd, 3, -1); count = safe_poll(pfd, 3, -1);
if (count <= 0) { if (count <= 0) {
#if 0 #if 0
if (waitpid(pid, &status, WNOHANG) <= 0) { if (safe_waitpid(pid, &status, WNOHANG) <= 0) {
/* Weird. CGI didn't exit and no fd's /* Weird. CGI didn't exit and no fd's
* are ready, yet poll returned?! */ * are ready, yet poll returned?! */
continue; continue;

View File

@ -944,7 +944,7 @@ static int doit(char *str)
execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ); execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ);
exit(127); exit(127);
} }
waitpid(child, &status, 0); safe_waitpid(child, &status, 0);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
return 0; return 0;
} }
@ -1068,7 +1068,7 @@ static char *run_mapping(char *physical, struct mapping_defn_t * map)
fprintf(in, "%s\n", map->mapping[i]); fprintf(in, "%s\n", map->mapping[i]);
} }
fclose(in); fclose(in);
waitpid(pid, &status, 0); safe_waitpid(pid, &status, 0);
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
/* If the mapping script exited successfully, try to /* If the mapping script exited successfully, try to

View File

@ -1161,7 +1161,7 @@ static void reapchild(int sig ATTRIBUTE_UNUSED)
servtab_t *sep; servtab_t *sep;
for (;;) { for (;;) {
pid = wait3(&status, WNOHANG, NULL); pid = wait_any_nohang(&status);
if (pid <= 0) if (pid <= 0)
break; break;
for (sep = servtab; sep; sep = sep->se_next) for (sep = servtab; sep; sep = sep->se_next)

View File

@ -394,7 +394,7 @@ static void handle_sigchld(int sig)
/* Looping: more than one child may have exited */ /* Looping: more than one child may have exited */
while (1) { while (1) {
pid = waitpid(-1, NULL, WNOHANG); pid = wait_any_nohang(NULL);
if (pid <= 0) if (pid <= 0)
break; break;
ts = sessions; ts = sessions;

View File

@ -232,7 +232,7 @@ void udhcp_run_script(struct dhcpMessage *packet, const char *name)
name, NULL, envp); name, NULL, envp);
bb_perror_msg_and_die("script %s failed", client_config.script); bb_perror_msg_and_die("script %s failed", client_config.script);
} }
waitpid(pid, NULL, 0); safe_waitpid(pid, NULL, 0);
for (curr = envp; *curr; curr++) for (curr = envp; *curr; curr++)
free(*curr); free(*curr);
free(envp); free(envp);

View File

@ -282,8 +282,7 @@ static unsigned custom(struct svdir *s, char c)
execve(a, prog, environ); execve(a, prog, environ);
fatal_cannot("run control/?"); fatal_cannot("run control/?");
} }
while (wait_pid(&w, pid) == -1) { while (safe_waitpid(pid, &w, 0) == -1) {
if (errno == EINTR) continue;
warn_cannot("wait for child control/?"); warn_cannot("wait for child control/?");
return 0; return 0;
} }
@ -593,7 +592,7 @@ int runsv_main(int argc, char **argv)
int child; int child;
int wstat; int wstat;
child = wait_nohang(&wstat); child = wait_any_nohang(&wstat);
if (!child) if (!child)
break; break;
if ((child == -1) && (errno != EINTR)) if ((child == -1) && (errno != EINTR))

View File

@ -252,7 +252,7 @@ int runsvdir_main(int argc, char **argv)
for (;;) { for (;;) {
/* collect children */ /* collect children */
for (;;) { for (;;) {
pid = wait_nohang(&wstat); pid = wait_any_nohang(&wstat);
if (pid <= 0) if (pid <= 0)
break; break;
for (i = 0; i < svnum; i++) { for (i = 0; i < svnum; i++) {

View File

@ -333,8 +333,7 @@ static int checkscript(void)
bb_perror_msg(WARN"cannot %s child %s/check", "run", *service); bb_perror_msg(WARN"cannot %s child %s/check", "run", *service);
return 0; return 0;
} }
while (wait_pid(&w, pid) == -1) { while (safe_waitpid(pid, &w, 0) == -1) {
if (errno == EINTR) continue;
bb_perror_msg(WARN"cannot %s child %s/check", "wait for", *service); bb_perror_msg(WARN"cannot %s child %s/check", "wait for", *service);
return 0; return 0;
} }

View File

@ -265,7 +265,7 @@ static unsigned processorstop(struct logdir *ld)
if (ld->ppid) { if (ld->ppid) {
sig_unblock(SIGHUP); sig_unblock(SIGHUP);
while (wait_pid(&wstat, ld->ppid) == -1) while (safe_waitpid(ld->ppid, &wstat, 0) == -1)
pause2cannot("wait for processor", ld->name); pause2cannot("wait for processor", ld->name);
sig_block(SIGHUP); sig_block(SIGHUP);
ld->ppid = 0; ld->ppid = 0;
@ -794,7 +794,7 @@ static void sig_child_handler(int sig_no)
if (verbose) if (verbose)
bb_error_msg(INFO"sig%s received", "child"); bb_error_msg(INFO"sig%s received", "child");
while ((pid = wait_nohang(&wstat)) > 0) { while ((pid = wait_any_nohang(&wstat)) > 0) {
for (l = 0; l < dirn; ++l) { for (l = 0; l < dirn; ++l) {
if (dir[l].ppid == pid) { if (dir[l].ppid == pid) {
dir[l].ppid = 0; dir[l].ppid = 0;

View File

@ -3768,7 +3768,7 @@ waitproc(int block, int *status)
#endif #endif
if (block == 0) if (block == 0)
flags |= WNOHANG; flags |= WNOHANG;
return wait3(status, flags, (struct rusage *)NULL); return waitpid(-1, status, flags); // safe_waitpid?
} }
/* /*

View File

@ -1649,6 +1649,7 @@ static int checkjobs(struct pipe* fg_pipe)
// + killall -STOP cat // + killall -STOP cat
wait_more: wait_more:
// TODO: safe_waitpid?
while ((childpid = waitpid(-1, &status, attributes)) > 0) { while ((childpid = waitpid(-1, &status, attributes)) > 0) {
const int dead = WIFEXITED(status) || WIFSIGNALED(status); const int dead = WIFEXITED(status) || WIFSIGNALED(status);

View File

@ -4162,7 +4162,7 @@ static int grave(int quoted)
return 0; return 0;
} }
if (i != 0) { if (i != 0) {
waitpid(i, NULL, 0); waitpid(i, NULL, 0); // safe_waitpid?
global_env.iop->argp->aword = ++cp; global_env.iop->argp->aword = ++cp;
close(pf[1]); close(pf[1]);
PUSHIO(afile, remap(pf[0]), PUSHIO(afile, remap(pf[0]),