*: introduce and use xfork() and xvfork()
No binary (build failed)
—
(log yok)
| @@ -82,11 +82,8 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle) | |
| memset(tar_env, 0, sizeof(tar_env)); | |
| xpipe(p); | |
| - | pid = BB_MMU ? fork() : vfork(); |
| - | switch (pid) { |
| - | case -1: |
| - | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); |
| - | case 0: |
| + | pid = BB_MMU ? xfork() : xvfork(); |
| + | if (pid == 0) { |
| /* Child */ | |
| /* str2env(tar_env, TAR_FILETYPE, "f"); - parent should do it once */ | |
| oct2env(tar_env, TAR_MODE, file_header->mode); | |
| @@ -19,19 +19,9 @@ void FAST_FUNC open_transformer(int fd, | |
| int pid; | |
| xpiped_pair(fd_pipe); | |
| - | |
| - | #if BB_MMU |
| - | pid = fork(); |
| - | if (pid == -1) |
| - | bb_perror_msg_and_die("vfork" + 1); |
| - | #else |
| - | pid = vfork(); |
| - | if (pid == -1) |
| - | bb_perror_msg_and_die("vfork"); |
| - | #endif |
| - | |
| + | pid = BB_MMU ? xfork() : xvfork(); |
| if (pid == 0) { | |
| - | /* child process */ |
| + | /* Child */ |
| close(fd_pipe.rd); /* we don't want to read from the parent */ | |
| // FIXME: error check? | |
| #if BB_MMU | |
| @@ -514,9 +514,7 @@ static void NOINLINE vfork_compressor(int tar_fd, int gzip) | |
| (void) &zip_exec; | |
| # endif | |
| - | gzipPid = vfork(); |
| - | if (gzipPid < 0) |
| - | bb_perror_msg_and_die("vfork"); |
| + | gzipPid = xvfork(); |
| if (gzipPid == 0) { | |
| /* child */ | |
| @@ -409,9 +409,7 @@ int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv) | |
| /* DAEMON_DEVNULL_STDIO is superfluous - | |
| * it's always done by bb_daemonize() */ | |
| #else | |
| - | pid_t pid = vfork(); |
| - | if (pid < 0) /* error */ |
| - | bb_perror_msg_and_die("vfork"); |
| + | pid_t pid = xvfork(); |
| if (pid != 0) { | |
| /* parent */ | |
| /* why _exit? the child may have changed the stack, | |
| @@ -612,7 +612,7 @@ static int execute(const char *type, const char *device, const char *mntpt, | |
| if (noexecute) | |
| pid = -1; | |
| else if ((pid = fork()) < 0) { | |
| - | perror("fork"); |
| + | perror("vfork"+1); |
| return errno; | |
| } else if (pid == 0) { | |
| if (!interactive) | |
| @@ -841,6 +841,19 @@ int bb_execvp(const char *file, char *const argv[]) FAST_FUNC; | |
| #endif | |
| int BB_EXECVP_or_die(char **argv) NORETURN FAST_FUNC; | |
| + | /* xvfork() can't be a _function_, return after vfork mangles stack |
| + | * in the parent. It must be a macro. */ |
| + | #define xvfork() \ |
| + | ({ \ |
| + | pid_t bb__xvfork_pid = vfork(); \ |
| + | if (bb__xvfork_pid < 0) \ |
| + | bb_perror_msg_and_die("vfork"); \ |
| + | bb__xvfork_pid; \ |
| + | }) |
| + | #if BB_MMU |
| + | pid_t xfork(void) FAST_FUNC; |
| + | #endif |
| + | |
| /* NOMMU friendy fork+exec: */ | |
| pid_t spawn(char **argv) FAST_FUNC; | |
| pid_t xspawn(char **argv) FAST_FUNC; | |
| @@ -886,7 +899,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char ** | |
| * Both of the above will redirect fd 0,1,2 to /dev/null and drop ctty | |
| * (will do setsid()). | |
| * | |
| - | * fork_or_rexec(argv) = bare-bones "fork" on MMU, |
| + | * fork_or_rexec(argv) = bare-bones fork on MMU, |
| * "vfork + re-exec ourself" on NOMMU. No fd redirection, no setsid(). | |
| * On MMU ignores argv. | |
| * | |
| @@ -902,19 +915,19 @@ enum { | |
| DAEMON_ONLY_SANITIZE = 8, /* internal use */ | |
| }; | |
| #if BB_MMU | |
| - | pid_t fork_or_rexec(void) FAST_FUNC; |
| enum { re_execed = 0 }; | |
| - | # define fork_or_rexec(argv) fork_or_rexec() |
| + | # define fork_or_rexec(argv) xfork() |
| # define bb_daemonize_or_rexec(flags, argv) bb_daemonize_or_rexec(flags) | |
| # define bb_daemonize(flags) bb_daemonize_or_rexec(flags, bogus) | |
| #else | |
| + | extern bool re_execed; |
| void re_exec(char **argv) NORETURN FAST_FUNC; | |
| pid_t fork_or_rexec(char **argv) FAST_FUNC; | |
| - | extern bool re_execed; |
| int BUG_fork_is_unavailable_on_nommu(void) FAST_FUNC; | |
| int BUG_daemon_is_unavailable_on_nommu(void) FAST_FUNC; | |
| void BUG_bb_daemonize_is_unavailable_on_nommu(void) FAST_FUNC; | |
| # define fork() BUG_fork_is_unavailable_on_nommu() | |
| + | # define xfork() BUG_fork_is_unavailable_on_nommu() |
| # define daemon(a,b) BUG_daemon_is_unavailable_on_nommu() | |
| # define bb_daemonize(a) BUG_bb_daemonize_is_unavailable_on_nommu() | |
| #endif | |
| @@ -427,9 +427,7 @@ int bootchartd_main(int argc UNUSED_PARAM, char **argv) | |
| } | |
| if (cmd == CMD_START && argv[2]) { /* "start PROG ARGS" */ | |
| - | pid_t pid = vfork(); |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die("vfork"); |
| + | pid_t pid = xvfork(); |
| if (pid == 0) { /* child */ | |
| argv += 2; | |
| execvp(argv[0], argv); | |
| @@ -224,26 +224,12 @@ pid_t FAST_FUNC fork_or_rexec(char **argv) | |
| /* Maybe we are already re-execed and come here again? */ | |
| if (re_execed) | |
| return 0; | |
| - | pid = vfork(); |
| - | if (pid < 0) /* wtf? */ |
| - | bb_perror_msg_and_die("vfork"); |
| + | pid = xvfork(); |
| if (pid) /* parent */ | |
| return pid; | |
| /* child - re-exec ourself */ | |
| re_exec(argv); | |
| } | |
| - | #else |
| - | /* Dance around (void)...*/ |
| - | #undef fork_or_rexec |
| - | pid_t FAST_FUNC fork_or_rexec(void) |
| - | { |
| - | pid_t pid; |
| - | pid = fork(); |
| - | if (pid < 0) /* wtf? */ |
| - | bb_perror_msg_and_die("fork"); |
| - | return pid; |
| - | } |
| - | #define fork_or_rexec(argv) fork_or_rexec() |
| #endif | |
| /* Due to a #define in libbb.h on MMU systems we actually have 1 argument - | |
| @@ -589,3 +589,14 @@ void FAST_FUNC generate_uuid(uint8_t *buf) | |
| /* variant = 10x */ | |
| buf[4 + 2 + 2] = (buf[4 + 2 + 2] & 0x3f) | 0x80; | |
| } | |
| + | |
| + | #if BB_MMU |
| + | pid_t FAST_FUNC xfork(void) |
| + | { |
| + | pid_t pid; |
| + | pid = fork(); |
| + | if (pid < 0) /* wtf? */ |
| + | bb_perror_msg_and_die("vfork"+1); |
| + | return pid; |
| + | } |
| + | #endif |
| @@ -54,9 +54,7 @@ void FAST_FUNC launch_helper(const char **argv) | |
| + (1 << SIGALRM) | |
| , signal_handler); | |
| - | G.helper_pid = vfork(); |
| - | if (G.helper_pid < 0) |
| - | bb_perror_msg_and_die("vfork"); |
| + | G.helper_pid = xvfork(); |
| i = (!G.helper_pid) * 2; // for parent:0, for child:2 | |
| close(pipes[i + 1]); // 1 or 3 - closing one write end | |
| @@ -309,10 +309,7 @@ static void create_cdev_if_doesnt_exist(const char* name, dev_t dev) | |
| static NOINLINE void start_shell_in_child(const char* tty_name) | |
| { | |
| - | int pid = vfork(); |
| - | if (pid < 0) { |
| - | bb_perror_msg_and_die("vfork"); |
| - | } |
| + | int pid = xvfork(); |
| if (pid == 0) { | |
| struct termios termchild; | |
| char *shell = getenv("SHELL"); | |
| @@ -20,10 +20,8 @@ | |
| static void edit_file(const struct passwd *pas, const char *file) | |
| { | |
| const char *ptr; | |
| - | int pid = vfork(); |
| + | int pid = xvfork(); |
| - | if (pid < 0) /* failure */ |
| - | bb_perror_msg_and_die("vfork"); |
| if (pid) { /* parent */ | |
| wait4pid(pid); | |
| return; | |
| @@ -51,9 +49,7 @@ static int open_as_user(const struct passwd *pas, const char *file) | |
| pid_t pid; | |
| char c; | |
| - | pid = vfork(); |
| - | if (pid < 0) /* ERROR */ |
| - | bb_perror_msg_and_die("vfork"); |
| + | pid = xvfork(); |
| if (pid) { /* PARENT */ | |
| if (wait4pid(pid) == 0) { | |
| /* exitcode 0: child says it can read */ | |
| @@ -372,9 +372,7 @@ static void run_command(char *const *cmd, resource_t *resp) | |
| void (*quit_signal)(int); | |
| resp->elapsed_ms = monotonic_ms(); | |
| - | pid = vfork(); |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die("vfork"); |
| + | pid = xvfork(); |
| if (pid == 0) { | |
| /* Child */ | |
| BB_EXECVP_or_die((char**)cmd); | |
| @@ -71,9 +71,7 @@ int timeout_main(int argc UNUSED_PARAM, char **argv) | |
| sv1 = argv[optind]; | |
| sv2 = argv[optind + 1]; | |
| #endif | |
| - | pid = vfork(); |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die("vfork"); |
| + | pid = xvfork(); |
| if (pid == 0) { | |
| /* Child: spawn grandchild and exit */ | |
| parent = getppid(); | |
| @@ -632,10 +632,7 @@ popen_ls(const char *opt) | |
| xpiped_pair(outfd); | |
| /*fflush_all(); - so far we dont use stdio on output */ | |
| - | pid = BB_MMU ? fork() : vfork(); |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); |
| - | |
| + | pid = BB_MMU ? xfork() : xvfork(); |
| if (pid == 0) { | |
| /* child */ | |
| #if !BB_MMU | |
| @@ -1041,12 +1041,10 @@ static int popen2(FILE **in, FILE **out, char *command, char *param) | |
| xpiped_pair(outfd); | |
| fflush_all(); | |
| - | pid = vfork(); |
| + | pid = xvfork(); |
| - | switch (pid) { |
| - | case -1: /* failure */ |
| - | bb_perror_msg_and_die("vfork"); |
| - | case 0: /* child */ |
| + | if (pid == 0) { |
| + | /* Child */ |
| /* NB: close _first_, then move fds! */ | |
| close(infd.wr); | |
| close(outfd.rd); | |
| @@ -1271,7 +1271,7 @@ int inetd_main(int argc UNUSED_PARAM, char **argv) | |
| pid = vfork(); | |
| if (pid < 0) { /* fork error */ | |
| - | bb_perror_msg("fork"); |
| + | bb_perror_msg("vfork"+1); |
| sleep(1); | |
| restore_sigmask(&omask); | |
| maybe_close(accepted_fd); | |
| @@ -216,10 +216,8 @@ int nc_main(int argc, char **argv) | |
| if (execparam) { | |
| pid_t pid; | |
| /* With more than one -l, repeatedly act as server */ | |
| - | if (do_listen > 1 && (pid = vfork()) != 0) { |
| - | /* parent or error */ |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die("vfork"); |
| + | if (do_listen > 1 && (pid = xvfork()) != 0) { |
| + | /* parent */ |
| /* prevent zombies */ | |
| signal(SIGCHLD, SIG_IGN); | |
| close(cfd); | |
| @@ -86,7 +86,7 @@ void exec_kernel_doc(char **svec) | |
| fflush(stdout); | |
| switch(pid=fork()) { | |
| case -1: | |
| - | perror("fork"); |
| + | perror("vfork"+1); |
| exit(1); | |
| case 0: | |
| rflen = strlen(getenv("SRCTREE")); | |
| @@ -3208,15 +3208,11 @@ static void setup_heredoc(struct redir_struct *redir) | |
| #if !BB_MMU | |
| to_free = NULL; | |
| #endif | |
| - | pid = vfork(); |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die("vfork"); |
| + | pid = xvfork(); |
| if (pid == 0) { | |
| /* child */ | |
| disable_restore_tty_pgrp_on_exit(); | |
| - | pid = BB_MMU ? fork() : vfork(); |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); |
| + | pid = BB_MMU ? xfork() : xvfork(); |
| if (pid != 0) | |
| _exit(0); | |
| /* grandchild */ | |
| @@ -4450,7 +4446,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |
| argv_expanded = NULL; | |
| if (command->pid < 0) { /* [v]fork failed */ | |
| /* Clearly indicate, was it fork or vfork */ | |
| - | bb_perror_msg(BB_MMU ? "fork" : "vfork"); |
| + | bb_perror_msg(BB_MMU ? "vfork"+1 : "vfork"); |
| } else { | |
| pi->alive_cmds++; | |
| #if ENABLE_HUSH_JOB | |
| @@ -5586,10 +5582,7 @@ static FILE *generate_stream_from_string(const char *s, pid_t *pid_p) | |
| # endif | |
| xpipe(channel); | |
| - | pid = BB_MMU ? fork() : vfork(); |
| - | if (pid < 0) |
| - | bb_perror_msg_and_die(BB_MMU ? "fork" : "vfork"); |
| - | |
| + | pid = BB_MMU ? xfork() : xvfork(); |
| if (pid == 0) { /* child */ | |
| disable_restore_tty_pgrp_on_exit(); | |
| /* Process substitution is not considered to be usual | |
| @@ -88,10 +88,7 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |
| /* TODO: SIGWINCH? pass window size changes down to slave? */ | |
| - | child_pid = vfork(); |
| - | if (child_pid < 0) { |
| - | bb_perror_msg_and_die("vfork"); |
| - | } |
| + | child_pid = xvfork(); |
| if (child_pid) { | |
| /* parent */ | |