diff options
author | Jari Aalto <jari.aalto@cante.net> | 2009-02-19 22:21:29 +0000 |
---|---|---|
committer | Jari Aalto <jari.aalto@cante.net> | 2009-09-12 16:47:02 +0000 |
commit | 17345e5ad288f7543b77b23a25aa380eacc279f2 (patch) | |
tree | 8ac954624147c08ebe1f72f38e0fa5e0416ce87d /execute_cmd.c | |
parent | 3185942a5234e26ab13fa02f9c51d340cec514f8 (diff) | |
download | android_external_bash-17345e5ad288f7543b77b23a25aa380eacc279f2.tar.gz android_external_bash-17345e5ad288f7543b77b23a25aa380eacc279f2.tar.bz2 android_external_bash-17345e5ad288f7543b77b23a25aa380eacc279f2.zip |
Imported from ../bash-4.0.tar.gz.
Diffstat (limited to 'execute_cmd.c')
-rw-r--r-- | execute_cmd.c | 109 |
1 files changed, 98 insertions, 11 deletions
diff --git a/execute_cmd.c b/execute_cmd.c index 609dd31..4843f4b 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -513,7 +513,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, int pipe_in, pipe_out; struct fd_bitmap *fds_to_close; { - int exec_result, invert, ignore_return, was_error_trap; + int exec_result, user_subshell, invert, ignore_return, was_error_trap; REDIRECT *my_undo_list, *exec_undo_list; volatile int last_pid; volatile int save_line_number; @@ -557,6 +557,8 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, return (execute_coproc (command, pipe_in, pipe_out, fds_to_close)); #endif + user_subshell = command->type == cm_subshell || ((command->flags & CMD_WANT_SUBSHELL) != 0); + if (command->type == cm_subshell || (command->flags & (CMD_WANT_SUBSHELL|CMD_FORCE_SUBSHELL)) || (shell_control_structure (command->type) && @@ -590,6 +592,10 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, if (asynchronous == 0) { + was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; + invert = (command->flags & CMD_INVERT_RETURN) != 0; + ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; + last_command_exit_value = wait_for (paren_pid); /* If we have to, invert the return value. */ @@ -600,6 +606,20 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, else exec_result = last_command_exit_value; + + if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + run_error_trap (); + } + + if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + run_pending_traps (); + jump_to_top_level (ERREXIT); + } + return (last_command_exit_value = exec_result); } else @@ -741,10 +761,8 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out, } } - /* 10/6/2008 -- added test for pipe_in and pipe_out because they indicate - the presence of a pipeline, and (until Posix changes things), a - pipeline failure should not cause the parent shell to exit on an - unsuccessful return status, even in the presence of errexit.. */ + /* 2009/02/13 -- pipeline failure is processed elsewhere. This handles + only the failure of a simple command. */ if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS) { last_command_exit_value = exec_result; @@ -1056,8 +1074,11 @@ print_formatted_time (fp, format, rs, rsf, us, usf, ss, ssf, cpu) else if (s[1] == 'P') { s++; +#if 0 + /* clamp CPU usage at 100% */ if (cpu > 10000) cpu = 10000; +#endif sum = cpu / 100; sum_frac = (cpu % 100) * 10; len = mkfmt (ts, 2, 0, sum, sum_frac); @@ -1438,6 +1459,7 @@ static struct cpelement *cpe_alloc __P((struct coproc *)); static void cpe_dispose __P((struct cpelement *)); static struct cpelement *cpl_add __P((struct coproc *)); static struct cpelement *cpl_delete __P((pid_t)); +static void cpl_reap __P((void)); static void cpl_flush __P((void)); static struct cpelement *cpl_search __P((pid_t)); static struct cpelement *cpl_searchbyname __P((char *)); @@ -1447,8 +1469,7 @@ Coproc sh_coproc = { 0, NO_PID, -1, -1, 0, 0 }; cplist_t coproc_list = {0, 0, 0}; -/* Functions to manage the list of exited background pids whose status has - been saved. */ +/* Functions to manage the list of coprocs */ static struct cpelement * cpe_alloc (cp) @@ -1527,6 +1548,37 @@ cpl_delete (pid) return (p); } +static void +cpl_reap () +{ + struct cpelement *prev, *p; + + for (prev = p = coproc_list.head; p; prev = p, p = p->next) + if (p->coproc->c_flags & COPROC_DEAD) + { + prev->next = p->next; /* remove from list */ + + /* Housekeeping in the border cases. */ + if (p == coproc_list.head) + coproc_list.head = coproc_list.head->next; + else if (p == coproc_list.tail) + coproc_list.tail = prev; + + coproc_list.ncoproc--; + if (coproc_list.ncoproc == 0) + coproc_list.head = coproc_list.tail = 0; + else if (coproc_list.ncoproc == 1) + coproc_list.tail = coproc_list.head; /* just to make sure */ + +#if defined (DEBUG) + itrace("cpl_reap: deleting %d", p->coproc->c_pid); +#endif + + coproc_dispose (p->coproc); + cpe_dispose (p); + } +} + /* Clear out the list of saved statuses */ static void cpl_flush () @@ -1680,6 +1732,16 @@ coproc_closeall () } void +coproc_reap () +{ + struct coproc *cp; + + cp = &sh_coproc; + if (cp && (cp->c_flags & COPROC_DEAD)) + coproc_dispose (cp); +} + +void coproc_rclose (cp, fd) struct coproc *cp; int fd; @@ -1751,9 +1813,9 @@ coproc_fdrestore (cp) cp->c_rfd = cp->c_rsave; cp->c_wfd = cp->c_wsave; } - + void -coproc_pidchk (pid) +coproc_pidchk (pid, status) pid_t pid; { struct coproc *cp; @@ -1764,7 +1826,14 @@ coproc_pidchk (pid) itrace("coproc_pidchk: pid %d has died", pid); #endif if (cp) - coproc_dispose (cp); + { + cp->c_status = status; + cp->c_flags |= COPROC_DEAD; + cp->c_flags &= ~COPROC_RUNNING; +#if 0 + coproc_dispose (cp); +#endif + } } void @@ -2035,7 +2104,7 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close) { REDIRECT *rp; COMMAND *tc, *second; - int ignore_return, exec_result; + int ignore_return, exec_result, was_error_trap, invert; ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; @@ -2101,7 +2170,25 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close) break; case '|': + was_error_trap = signal_is_trapped (ERROR_TRAP) && signal_is_ignored (ERROR_TRAP) == 0; + invert = (command->flags & CMD_INVERT_RETURN) != 0; + ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0; + exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close); + + if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + run_error_trap (); + } + + if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS) + { + last_command_exit_value = exec_result; + run_pending_traps (); + jump_to_top_level (ERREXIT); + } + break; case AND_AND: |