From d2c450ce811454fb77679d049538530d2cf54dd8 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Tue, 8 Jan 2008 20:32:12 +0000 Subject: hush: report [v]fork failures hush: more correct handling of piping config: add CONFIG_NOMMU --- Config.in | 11 ++++++++++ TODO_config_nommu | 12 ++++++++--- include/platform.h | 5 +++-- shell/hush.c | 62 ++++++++++++++++++++++++++---------------------------- 4 files changed, 53 insertions(+), 37 deletions(-) diff --git a/Config.in b/Config.in index fa48ddd63..d2bb63200 100644 --- a/Config.in +++ b/Config.in @@ -280,6 +280,17 @@ config STATIC Most people will leave this set to 'N'. +config NOMMU + bool "Force NOMMU build" + default n + help + Busybox tries to detect whether architecture it is being + built against supports MMU or not. If this detection fails, + or if you want to build NOMMU version of busybox for testing, + you may force NOMMU build here. + + Most people will leave this set to 'N'. + config BUILD_LIBBUSYBOX bool "Build shared libbusybox" default n diff --git a/TODO_config_nommu b/TODO_config_nommu index a4cc344ab..81db6db2f 100644 --- a/TODO_config_nommu +++ b/TODO_config_nommu @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Busybox version: 1.9.0.svn -# Mon Dec 24 14:21:28 2007 +# Busybox version: 1.10.0.svn +# Tue Jan 8 20:29:22 2008 # CONFIG_HAVE_DOT_CONFIG=y @@ -39,6 +39,7 @@ CONFIG_FEATURE_HAVE_RPC=y # Build Options # # CONFIG_STATIC is not set +CONFIG_NOMMU=y # CONFIG_BUILD_LIBBUSYBOX is not set # CONFIG_FEATURE_INDIVIDUAL is not set # CONFIG_FEATURE_SHARED_BUSYBOX is not set @@ -222,6 +223,7 @@ CONFIG_FEATURE_STAT_FORMAT=y CONFIG_STTY=y CONFIG_SUM=y CONFIG_SYNC=y +CONFIG_TAC=y CONFIG_TAIL=y CONFIG_FEATURE_FANCY_TAIL=y CONFIG_TEE=y @@ -368,6 +370,8 @@ CONFIG_FEATURE_XARGS_SUPPORT_ZERO_TERM=y # CONFIG_INIT is not set # CONFIG_DEBUG_INIT is not set # CONFIG_FEATURE_USE_INITTAB is not set +# CONFIG_FEATURE_KILL_REMOVED is not set +CONFIG_FEATURE_KILL_DELAY=0 # CONFIG_FEATURE_INIT_SCTTY is not set # CONFIG_FEATURE_INIT_SYSLOG is not set # CONFIG_FEATURE_EXTRA_QUIET is not set @@ -679,6 +683,8 @@ CONFIG_FEATURE_PIDOF_OMIT=y CONFIG_PKILL=y CONFIG_PS=y CONFIG_FEATURE_PS_WIDE=y +CONFIG_FEATURE_PS_TIME=y +# CONFIG_FEATURE_PS_UNUSUAL_SYSTEMS is not set CONFIG_RENICE=y CONFIG_BB_SYSCTL=y CONFIG_TOP=y @@ -713,7 +719,7 @@ CONFIG_FEATURE_SH_IS_NONE=y # CONFIG_ASH_EXPAND_PRMT is not set CONFIG_HUSH=y CONFIG_HUSH_HELP=y -# CONFIG_HUSH_INTERACTIVE is not set +CONFIG_HUSH_INTERACTIVE=y # CONFIG_HUSH_JOB is not set CONFIG_HUSH_TICK=y CONFIG_HUSH_IF=y diff --git a/include/platform.h b/include/platform.h index edb0f8ab0..4c38c6ae4 100644 --- a/include/platform.h +++ b/include/platform.h @@ -231,8 +231,9 @@ typedef unsigned smalluint; * for a mmu-less system; the user should pass EXTRA_CFLAGS="-DBB_NOMMU" * on his own. */ -#if defined __UCLIBC__ && __UCLIBC_MAJOR__ >= 0 && __UCLIBC_MINOR__ >= 9 && \ - __UCLIBC_SUBLEVEL__ > 28 && !defined __ARCH_USE_MMU__ +#if ENABLE_NOMMU || \ + (defined __UCLIBC__ && __UCLIBC_MAJOR__ >= 0 && __UCLIBC_MINOR__ >= 9 && \ + __UCLIBC_SUBLEVEL__ > 28 && !defined __ARCH_USE_MMU__) #define BB_MMU 0 #define BB_NOMMU 1 #define USE_FOR_NOMMU(...) __VA_ARGS__ diff --git a/shell/hush.c b/shell/hush.c index b08fe10b6..9dc85d0ba 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1777,8 +1777,8 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe) static int run_pipe_real(struct pipe *pi) { int i; - int nextin, nextout; - int pipefds[2]; /* pipefds[0] is for reading */ + int nextin; + int pipefds[2]; /* pipefds[0] is for reading */ struct child_prog *child; const struct built_in_command *x; char *p; @@ -1789,7 +1789,6 @@ static int run_pipe_real(struct pipe *pi) debug_printf_exec("run_pipe_real start: single_fg=%d\n", single_fg); - nextin = 0; #if ENABLE_HUSH_JOB pi->pgrp = -1; #endif @@ -1874,13 +1873,14 @@ static int run_pipe_real(struct pipe *pi) #endif } - /* Going to fork a child per each pipe member */ - pi->running_progs = 0; - /* Disable job control signals for shell (parent) and * for initial child code after fork */ set_jobctrl_sighandler(SIG_IGN); + /* Going to fork a child per each pipe member */ + pi->running_progs = 0; + nextin = 0; + for (i = 0; i < pi->num_progs; i++) { child = &(pi->progs[i]); if (child->argv) @@ -1889,24 +1889,20 @@ static int run_pipe_real(struct pipe *pi) debug_printf_exec(": pipe member with no argv\n"); /* pipes are inserted between pairs of commands */ - if ((i + 1) < pi->num_progs) { - pipe(pipefds); - nextout = pipefds[1]; - } else { - nextout = 1; - pipefds[0] = -1; - } + pipefds[0] = 0; + pipefds[1] = 1; + if ((i + 1) < pi->num_progs) + xpipe(pipefds); - /* XXX test for failed fork()? */ #if BB_MMU child->pid = fork(); #else child->pid = vfork(); #endif if (!child->pid) { /* child */ +#if ENABLE_HUSH_JOB /* Every child adds itself to new process group * with pgid == pid of first child in pipe */ -#if ENABLE_HUSH_JOB if (run_list_level == 1 && interactive_fd) { /* Don't do pgrp restore anymore on fatal signals */ set_fatal_sighandler(SIG_DFL); @@ -1919,12 +1915,10 @@ static int run_pipe_real(struct pipe *pi) } } #endif - /* in non-interactive case fatal sigs are already SIG_DFL */ xmove_fd(nextin, 0); - xmove_fd(nextout, 1); - if (pipefds[0] != -1) { - close(pipefds[0]); /* opposite end of our output pipe */ - } + xmove_fd(pipefds[1], 1); /* write end */ + if (pipefds[0] > 1) + close(pipefds[0]); /* read end */ /* Like bash, explicit redirects override pipes, * and the pipe fd is available for dup'ing. */ setup_redirects(child, NULL); @@ -1933,25 +1927,29 @@ static int run_pipe_real(struct pipe *pi) set_jobctrl_sighandler(SIG_DFL); set_misc_sighandler(SIG_DFL); signal(SIGCHLD, SIG_DFL); - pseudo_exec(child); + pseudo_exec(child); /* does not return */ } - pi->running_progs++; - + if (child->pid < 0) { /* [v]fork failed */ + /* Clearly indicate, was it fork or vfork */ + bb_perror_msg(BB_MMU ? "cannot fork" : "cannot vfork"); + } else { + pi->running_progs++; #if ENABLE_HUSH_JOB - /* Second and next children need to know pid of first one */ - if (pi->pgrp < 0) - pi->pgrp = child->pid; + /* Second and next children need to know pid of first one */ + if (pi->pgrp < 0) + pi->pgrp = child->pid; #endif - if (nextin != 0) - close(nextin); - if (nextout != 1) - close(nextout); + } - /* If there isn't another process, nextin is garbage - but it doesn't matter */ + if (i) + close(nextin); + if ((i + 1) < pi->num_progs) + close(pipefds[1]); /* write end */ + /* Pass read (output) pipe end to next iteration */ nextin = pipefds[0]; } + debug_printf_exec("run_pipe_real return -1\n"); return -1; } -- cgit v1.2.3