From 246439954279ef3460e2ab127eef4fbf2a133208 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Sat, 1 Nov 2014 16:59:17 -0500 Subject: [PATCH] Convert additional vfork calls to xvfork_and_run. --- shell/hush.c | 60 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/shell/hush.c b/shell/hush.c index ee19e8bf1..e1f9ccda8 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -6008,6 +6008,15 @@ static int process_command_subs(o_string *dest, const char *s) #endif /* ENABLE_HUSH_TICK */ +static void xvforked_child(void *) NORETURN; +static void xforked_grandchild(void *) NORETURN; +struct grandchild_args { + struct redir_struct *redir; + struct fd_pair *pair_p; + char ***to_free_p; + const char *heredoc; +}; + static void setup_heredoc(struct redir_struct *redir) { struct fd_pair pair; @@ -6057,23 +6066,15 @@ static void setup_heredoc(struct redir_struct *redir) #if !BB_MMU to_free = NULL; #endif - pid = xvfork(); - if (pid == 0) { - /* child */ - disable_restore_tty_pgrp_on_exit(); - pid = BB_MMU ? xfork() : xvfork(); - if (pid != 0) - _exit(0); - /* grandchild */ - close(redir->rd_fd); /* read side of the pipe */ -#if BB_MMU - full_write(pair.wr, heredoc, len); /* may loop or block */ - _exit(0); -#else - /* Delegate blocking writes to another process */ - xmove_fd(pair.wr, STDOUT_FILENO); - re_execute_shell(&to_free, heredoc, NULL, NULL, NULL); -#endif + + { + struct grandchild_args args = { + redir, + &pair, + &to_free, + heredoc + }; + pid = xvfork_and_run(xvforked_child, &args); } /* parent */ #if ENABLE_HUSH_FAST @@ -6089,6 +6090,31 @@ static void setup_heredoc(struct redir_struct *redir) wait(NULL); /* wait till child has died */ } +static void xvforked_child(void *grandchild_args) { + /* child */ + pid_t pid; + disable_restore_tty_pgrp_on_exit(); + pid = BB_MMU ? xfork() : xvfork_and_run(xforked_grandchild, grandchild_args); + if (pid != 0) + _exit(0); + xforked_grandchild(grandchild_args); // Only get here in BB_MMU case +} + +static void xforked_grandchild(void *args_struct) { + struct grandchild_args *args = (struct grandchild_args *)args_struct; + /* grandchild */ + close(args->redir->rd_fd); /* read side of the pipe */ +#if BB_MMU + full_write(args->pair_p->wr, args->heredoc, len); /* may loop or block */ + _exit(0); +#else + /* Delegate blocking writes to another process */ + xmove_fd(args->pair_p->wr, STDOUT_FILENO); + re_execute_shell(args->to_free_p, args->heredoc, NULL, NULL, NULL); +#endif +} + + /* squirrel != NULL means we squirrel away copies of stdin, stdout, * and stderr if they are redirected. */ static int setup_redirects(struct command *prog, int squirrel[])