libbb: introduce and use safe_waitpid (loops in EINTR) *: use more approproate (shorter) versions of wait()
No binary (build failed)
—
(log yok)
| @@ -610,7 +610,7 @@ static int writeTarFile(const int tar_fd, const int verboseFlag, | |
| if (gzipPid) { | |
| int status; | |
| - | if (waitpid(gzipPid, &status, 0) == -1) |
| + | if (safe_waitpid(gzipPid, &status, 0) == -1) |
| bb_perror_msg("waitpid"); | |
| else if (!WIFEXITED(status) || WEXITSTATUS(status)) | |
| /* 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 */ | |
| /* Wait for any child without blocking */ | |
| - | if (waitpid(-1, &status, WNOHANG) < 0) |
| + | if (wait_any_nohang(&status) < 0) |
| /* wait failed?! I'm confused... */ | |
| return; | |
| @@ -587,9 +587,9 @@ pid_t xspawn(char **argv); | |
| * if (rc < 0) bb_perror_msg("%s", argv[0]); | |
| * if (rc > 0) bb_error_msg("exit code: %d", rc); | |
| */ | |
| + | int safe_waitpid(int pid, int *wstat, int options); |
| int wait4pid(int pid); | |
| - | int wait_pid(int *wstat, int pid); |
| - | int wait_nohang(int *wstat); |
| + | int wait_any_nohang(int *wstat); |
| #define wait_crashed(w) ((w) & 127) | |
| #define wait_exitcode(w) ((w) >> 8) | |
| #define wait_stopsig(w) ((w) >> 8) | |
| @@ -95,9 +95,14 @@ static const char *const environment[] = { | |
| /* Function prototypes */ | |
| static void delete_init_action(struct init_action *a); | |
| - | static int waitfor(pid_t pid); |
| 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) | |
| { | |
| @@ -465,19 +470,6 @@ static pid_t run(const struct init_action *a) | |
| _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 */ | |
| static void run_actions(int action) | |
| { | |
| @@ -520,7 +512,7 @@ static void init_reboot(unsigned long magic) | |
| reboot(magic); | |
| _exit(0); | |
| } | |
| - | waitpid(pid, NULL, 0); |
| + | waitfor(pid); |
| } | |
| 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 */ | |
| sleep(1); | |
| - | /* Wait for a child process to exit */ |
| + | /* Wait for any child process to exit */ |
| wpid = wait(NULL); | |
| while (wpid > 0) { | |
| /* 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 */ | |
| - | wpid = waitpid(-1, NULL, WNOHANG); |
| + | wpid = wait_any_nohang(NULL); |
| } | |
| } | |
| } | |
| @@ -121,7 +121,7 @@ static void sig_child_handler(int sig) | |
| int wstat; | |
| int pid; | |
| - | while ((pid = wait_nohang(&wstat)) > 0) { |
| + | while ((pid = wait_any_nohang(&wstat)) > 0) { |
| if (max_per_host) | |
| ipsvd_perhost_remove(pid); | |
| if (cnum) | |
| @@ -66,6 +66,21 @@ pid_t xspawn(char **argv) | |
| 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. | |
| int wait4pid(int pid) | |
| { | |
| @@ -76,28 +91,18 @@ int wait4pid(int pid) | |
| /* we expect errno to be already set from failed [v]fork/exec */ | |
| return -1; | |
| } | |
| - | if (waitpid(pid, &status, 0) == -1) |
| + | if (safe_waitpid(pid, &status, 0) == -1) |
| return -1; | |
| if (WIFEXITED(status)) | |
| return WEXITSTATUS(status); | |
| if (WIFSIGNALED(status)) | |
| return WTERMSIG(status) + 1000; | |
| return 0; | |
| - | } |
| - | |
| - | int wait_nohang(int *wstat) |
| - | { |
| - | return waitpid(-1, wstat, WNOHANG); |
| - | } |
| - | |
| - | int wait_pid(int *wstat, int pid) |
| - | { |
| - | int r; |
| - | |
| - | do |
| - | r = waitpid(pid, wstat, 0); |
| - | while ((r == -1) && (errno == EINTR)); |
| - | return r; |
| + | if (WIFEXITED(status)) |
| + | return WEXITSTATUS(status); |
| + | if (WIFSIGNALED(status)) |
| + | return WTERMSIG(status) + 1000; |
| + | return 0; |
| } | |
| #if ENABLE_FEATURE_PREFER_APPLETS | |
| @@ -756,7 +756,7 @@ static int CheckJobs(void) | |
| for (line = file->cf_LineBase; line; line = line->cl_Next) { | |
| if (line->cl_Pid > 0) { | |
| 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) { | |
| EndJob(file->cf_User, line); | |
| @@ -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); | |
| if (count <= 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 | |
| * are ready, yet poll returned?! */ | |
| continue; | |
| @@ -944,7 +944,7 @@ static int doit(char *str) | |
| execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, NULL, my_environ); | |
| exit(127); | |
| } | |
| - | waitpid(child, &status, 0); |
| + | safe_waitpid(child, &status, 0); |
| if (!WIFEXITED(status) || WEXITSTATUS(status) != 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]); | |
| } | |
| fclose(in); | |
| - | waitpid(pid, &status, 0); |
| + | safe_waitpid(pid, &status, 0); |
| if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { | |
| /* If the mapping script exited successfully, try to | |
| @@ -1161,7 +1161,7 @@ static void reapchild(int sig ATTRIBUTE_UNUSED) | |
| servtab_t *sep; | |
| for (;;) { | |
| - | pid = wait3(&status, WNOHANG, NULL); |
| + | pid = wait_any_nohang(&status); |
| if (pid <= 0) | |
| break; | |
| for (sep = servtab; sep; sep = sep->se_next) | |
| @@ -394,7 +394,7 @@ static void handle_sigchld(int sig) | |
| /* Looping: more than one child may have exited */ | |
| while (1) { | |
| - | pid = waitpid(-1, NULL, WNOHANG); |
| + | pid = wait_any_nohang(NULL); |
| if (pid <= 0) | |
| break; | |
| ts = sessions; | |
| @@ -232,7 +232,7 @@ void udhcp_run_script(struct dhcpMessage *packet, const char *name) | |
| name, NULL, envp); | |
| 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++) | |
| free(*curr); | |
| free(envp); | |
| @@ -282,8 +282,7 @@ static unsigned custom(struct svdir *s, char c) | |
| execve(a, prog, environ); | |
| fatal_cannot("run control/?"); | |
| } | |
| - | while (wait_pid(&w, pid) == -1) { |
| - | if (errno == EINTR) continue; |
| + | while (safe_waitpid(pid, &w, 0) == -1) { |
| warn_cannot("wait for child control/?"); | |
| return 0; | |
| } | |
| @@ -593,7 +592,7 @@ int runsv_main(int argc, char **argv) | |
| int child; | |
| int wstat; | |
| - | child = wait_nohang(&wstat); |
| + | child = wait_any_nohang(&wstat); |
| if (!child) | |
| break; | |
| if ((child == -1) && (errno != EINTR)) | |
| @@ -252,7 +252,7 @@ int runsvdir_main(int argc, char **argv) | |
| for (;;) { | |
| /* collect children */ | |
| for (;;) { | |
| - | pid = wait_nohang(&wstat); |
| + | pid = wait_any_nohang(&wstat); |
| if (pid <= 0) | |
| break; | |
| for (i = 0; i < svnum; i++) { | |
| @@ -333,8 +333,7 @@ static int checkscript(void) | |
| bb_perror_msg(WARN"cannot %s child %s/check", "run", *service); | |
| return 0; | |
| } | |
| - | while (wait_pid(&w, pid) == -1) { |
| - | if (errno == EINTR) continue; |
| + | while (safe_waitpid(pid, &w, 0) == -1) { |
| bb_perror_msg(WARN"cannot %s child %s/check", "wait for", *service); | |
| return 0; | |
| } | |
| @@ -265,7 +265,7 @@ static unsigned processorstop(struct logdir *ld) | |
| if (ld->ppid) { | |
| sig_unblock(SIGHUP); | |
| - | while (wait_pid(&wstat, ld->ppid) == -1) |
| + | while (safe_waitpid(ld->ppid, &wstat, 0) == -1) |
| pause2cannot("wait for processor", ld->name); | |
| sig_block(SIGHUP); | |
| ld->ppid = 0; | |
| @@ -794,7 +794,7 @@ static void sig_child_handler(int sig_no) | |
| if (verbose) | |
| 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) { | |
| if (dir[l].ppid == pid) { | |
| dir[l].ppid = 0; | |
| @@ -3768,7 +3768,7 @@ waitproc(int block, int *status) | |
| #endif | |
| if (block == 0) | |
| flags |= WNOHANG; | |
| - | return wait3(status, flags, (struct rusage *)NULL); |
| + | return waitpid(-1, status, flags); // safe_waitpid? |
| } | |
| /* | |
| @@ -1649,6 +1649,7 @@ static int checkjobs(struct pipe* fg_pipe) | |
| // + killall -STOP cat | |
| wait_more: | |
| + | // TODO: safe_waitpid? |
| while ((childpid = waitpid(-1, &status, attributes)) > 0) { | |
| const int dead = WIFEXITED(status) || WIFSIGNALED(status); | |
| @@ -4162,7 +4162,7 @@ static int grave(int quoted) | |
| return 0; | |
| } | |
| if (i != 0) { | |
| - | waitpid(i, NULL, 0); |
| + | waitpid(i, NULL, 0); // safe_waitpid? |
| global_env.iop->argp->aword = ++cp; | |
| close(pf[1]); | |
| PUSHIO(afile, remap(pf[0]), | |