diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 8f22677d..e0049883 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -8676,3 +8676,29 @@ lib/readline/vi_mode.c - rl_vi_{delete,change,yank}_to: if we have a non-null _rl_vimvcxt, just reinitialize it so we don't have to allocate a new one. This is a change primarily for callback mode, and fixes a memory leak + +builtins/evalstring.c + - optimize_shell_function: try to optimize away the fork in the last + command in a shell function body, under certain conditions + +execute_cmd.c + - execute_function: attempt to optimize away forks in a shell function + that is already marked NO_FORK and being executed in a command + substitution + + 7/8 + --- +{jobs,nojobs,trap,unwind_prot}.c,lib/malloc/{malloc,table}.c + - interrupt_immediately: remove, no longer used + +jobs.c + - waitchld: don't perform asynchronous notification if we are currently + executing a builtin (executing_builtin != 0). Inspired by a report + from Godmar Back + + 7/9 + --- +lib/readline/signals.c + - _rl_handle_signal: block SIGTTOU while handling a SIGTTOU, since we + no longer run this in a signal handling context where SIGTTOIU would + be blocked diff --git a/builtins/common.h b/builtins/common.h index 0aecc9ce..a4f9275d 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -210,6 +210,7 @@ extern int should_suppress_fork PARAMS((COMMAND *)); extern int can_optimize_connection PARAMS((COMMAND *)); extern void optimize_fork PARAMS((COMMAND *)); extern void optimize_subshell_command PARAMS((COMMAND *)); +extern void optimize_shell_function PARAMS((COMMAND *)); /* Functions from evalfile.c */ extern int maybe_execute_file PARAMS((const char *, int)); diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 4240277e..3a6801dd 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -145,7 +145,27 @@ optimize_subshell_command (command) (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR)) optimize_subshell_command (command->value.Connection->second); } - + +void +optimize_shell_function (command) + COMMAND *command; +{ + COMMAND *fc; + + fc = (command->type == cm_group) ? command->value.Group->command : command; + + if (fc->type == cm_simple && should_suppress_fork (fc)) + { + fc->flags |= CMD_NO_FORK; + fc->value.Simple->flags |= CMD_NO_FORK; + } + else if (fc->type == cm_connection && can_optimize_connection (fc) && should_suppress_fork (fc->value.Connection->second)) + { + fc->value.Connection->second->flags |= CMD_NO_FORK; + fc->value.Connection->second->value.Simple->flags |= CMD_NO_FORK; + } +} + /* How to force parse_and_execute () to clean up after itself. */ void parse_and_execute_cleanup (old_running_trap) diff --git a/execute_cmd.c b/execute_cmd.c index 0ba17f6c..62d21171 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -4831,6 +4831,11 @@ execute_function (var, words, flags, fds_to_close, async, subshell) if (tc && (flags & CMD_IGNORE_RETURN)) tc->flags |= CMD_IGNORE_RETURN; + /* A limited attempt at optimization: shell functions at the end of command + substitutions that are already marked NO_FORK. */ + if (tc && (flags & CMD_NO_FORK) && (subshell_environment & SUBSHELL_COMSUB)) + optimize_shell_function (tc); + gs = sh_getopt_save_istate (); if (subshell == 0) { diff --git a/jobs.c b/jobs.c index b6c83802..237cc6cd 100644 --- a/jobs.c +++ b/jobs.c @@ -2758,8 +2758,7 @@ wait_sigint_handler (sig) { SigHandler *sigint_handler; - if (interrupt_immediately || - (this_shell_builtin && this_shell_builtin == wait_builtin)) + if (this_shell_builtin && this_shell_builtin == wait_builtin) { set_exit_status (128+SIGINT); restore_sigint_handler (); @@ -2771,20 +2770,12 @@ wait_sigint_handler (sig) { trap_handler (SIGINT); /* set pending_traps[SIGINT] */ wait_signal_received = SIGINT; - if (interrupt_immediately && wait_intr_flag) - { - interrupt_immediately = 0; - sh_longjmp (wait_intr_buf, 1); - } + if (wait_intr_flag) + sh_longjmp (wait_intr_buf, 1); else /* Let CHECK_WAIT_INTR handle it in wait_for/waitchld */ SIGRETURN (0); } - else if (interrupt_immediately) - { - ADDINTERRUPT; - QUIT; - } else /* wait_builtin but signal not trapped, treat as interrupt */ kill (getpid (), SIGINT); } @@ -3947,7 +3938,6 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc { if (posixly_correct && this_shell_builtin && this_shell_builtin == wait_builtin) { - interrupt_immediately = 0; /* This was trap_handler (SIGCHLD) but that can lose traps if children_exited > 1 */ queue_sigchld_trap (children_exited); @@ -3978,7 +3968,7 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc that has just changed state. If we notify asynchronously, and the job that this process belongs to is no longer running, then notify the user of that fact now. */ - if (asynchronous_notification && interactive) + if (asynchronous_notification && interactive && executing_builtin == 0) notify_of_job_status (); return (children_exited); @@ -4211,7 +4201,6 @@ run_sigchld_trap (nchild) unwind_protect_int (last_command_exit_value); unwind_protect_int (last_command_exit_signal); unwind_protect_var (last_made_pid); - unwind_protect_int (interrupt_immediately); unwind_protect_int (jobs_list_frozen); unwind_protect_pointer (the_pipeline); unwind_protect_pointer (subst_assign_varlist); diff --git a/lib/malloc/malloc.c b/lib/malloc/malloc.c index 94806972..439f8ef1 100644 --- a/lib/malloc/malloc.c +++ b/lib/malloc/malloc.c @@ -319,7 +319,7 @@ extern char *sbrk (); #endif /* !HAVE_DECL_SBRK */ #ifdef SHELL -extern int interrupt_immediately, running_trap; +extern int running_trap; extern int signal_is_trapped PARAMS((int)); #endif @@ -620,9 +620,9 @@ morecore (nu) blocked_sigs = 0; #ifdef SHELL # if defined (SIGCHLD) - if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD)) + if (running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD)) # else - if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT)) + if (running_trap || signal_is_trapped (SIGINT)) # endif #endif { diff --git a/lib/malloc/memtest.c b/lib/malloc/memtest.c index 15f81158..911567f9 100644 --- a/lib/malloc/memtest.c +++ b/lib/malloc/memtest.c @@ -33,8 +33,6 @@ #include "xmalloc.h" -int interrupt_immediately = 0; - static char xp[64]; main(int c, char **v) diff --git a/lib/malloc/table.c b/lib/malloc/table.c index b587eea6..e6acbf4a 100644 --- a/lib/malloc/table.c +++ b/lib/malloc/table.c @@ -29,7 +29,7 @@ #include "table.h" #ifdef SHELL -extern int interrupt_immediately, running_trap; +extern int running_trap; extern int signal_is_trapped PARAMS((int)); #endif @@ -174,7 +174,7 @@ mregister_alloc (tag, mem, size, file, line) /* Block all signals in case we are executed from a signal handler. */ blocked_sigs = 0; #ifdef SHELL - if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD)) + if (running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD)) #endif { _malloc_block_signals (&set, &oset); @@ -229,7 +229,7 @@ mregister_free (mem, size, file, line) /* Block all signals in case we are executed from a signal handler. */ blocked_sigs = 0; #ifdef SHELL - if (interrupt_immediately || running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD)) + if (running_trap || signal_is_trapped (SIGINT) || signal_is_trapped (SIGCHLD)) #endif { _malloc_block_signals (&set, &oset); diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 055de2ee..d773a452 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -219,17 +219,19 @@ _rl_handle_signal (int sig) #if defined (SIGTSTP) case SIGTSTP: case SIGTTIN: + case SIGTTOU: # if defined (HAVE_POSIX_SIGNALS) /* Block SIGTTOU so we can restore the terminal settings to something sane without stopping on SIGTTOU if we have been placed into the background. Even trying to get the current terminal pgrp with - tcgetpgrp() will generate SIGTTOU, so we don't bother. Don't bother - doing this if we've been stopped on SIGTTOU; it's already too late. */ + tcgetpgrp() will generate SIGTTOU, so we don't bother. We still do + this even if we've been stopped on SIGTTOU, since we handle signals + when we have returned from the signal handler and the signal is no + longer blocked. */ sigemptyset (&set); sigaddset (&set, SIGTTOU); sigprocmask (SIG_BLOCK, &set, (sigset_t *)NULL); # endif - case SIGTTOU: #endif /* SIGTSTP */ case SIGTERM: #if defined (SIGHUP) diff --git a/nojobs.c b/nojobs.c index 1a393491..c5fc83d9 100644 --- a/nojobs.c +++ b/nojobs.c @@ -785,20 +785,11 @@ wait_sigint_handler (sig) { last_command_exit_value = 128+SIGINT; restore_sigint_handler (); - interrupt_immediately = 0; trap_handler (SIGINT); /* set pending_traps[SIGINT] */ wait_signal_received = SIGINT; SIGRETURN (0); } - if (interrupt_immediately) - { - last_command_exit_value = EXECUTION_FAILURE; - restore_sigint_handler (); - ADDINTERRUPT; - QUIT; - } - wait_sigint_received = 1; SIGRETURN (0); diff --git a/parse.y b/parse.y index 4bb15029..25b42483 100644 --- a/parse.y +++ b/parse.y @@ -1644,9 +1644,9 @@ rewind_input_string () /* These two functions used to test the value of the HAVE_RESTARTABLE_SYSCALLS define, and just use getc/ungetc if it was defined, but since bash - installs its signal handlers without the SA_RESTART flag, some signals - (like SIGCHLD, SIGWINCH, etc.) received during a read(2) will not cause - the read to be restarted. We need to restart it ourselves. */ + installs most of its signal handlers without the SA_RESTART flag, some + signals received during a read(2) will not cause the read to be restarted. + We will need to restart it ourselves. */ static int yy_stream_get () diff --git a/sig.c b/sig.c index a643c21b..43f9e82a 100644 --- a/sig.c +++ b/sig.c @@ -526,7 +526,6 @@ termsig_sighandler (sig) terminating_signal = sig; - /* XXX - should this also trigger when interrupt_immediately is set? */ if (terminate_immediately) { #if defined (HISTORY) @@ -669,7 +668,8 @@ sigint_sighandler (sig) wait_signal_received = sig; SIGRETURN (0); } - + + /* This is no longer used, but this code block remains as a reminder. */ if (interrupt_immediately) { interrupt_immediately = 0; diff --git a/trap.c b/trap.c index 481dbccc..da071b35 100644 --- a/trap.c +++ b/trap.c @@ -499,13 +499,10 @@ trap_handler (sig) /* Set the event hook so readline will call it after the signal handlers finish executing, so if this interrupted character input we can get quick response. */ - if (RL_ISSTATE (RL_STATE_SIGHANDLER) && interrupt_immediately == 0) + if (RL_ISSTATE (RL_STATE_SIGHANDLER)) bashline_set_event_hook (); #endif - if (interrupt_immediately) - run_pending_traps (); - errno = oerrno; } diff --git a/unwind_prot.c b/unwind_prot.c index ef831d81..5703777f 100644 --- a/unwind_prot.c +++ b/unwind_prot.c @@ -108,21 +108,13 @@ uwp_init () } /* Run a function without interrupts. This relies on the fact that the - FUNCTION cannot change the value of interrupt_immediately. (I.e., does - not call QUIT (). */ + FUNCTION cannot call QUIT (). */ static void without_interrupts (function, arg1, arg2) VFunction *function; char *arg1, *arg2; { - int old_interrupt_immediately; - - old_interrupt_immediately = interrupt_immediately; - interrupt_immediately = 0; - (*function)(arg1, arg2); - - interrupt_immediately = old_interrupt_immediately; } /* Start the beginning of a region. */