From: Chet Ramey Date: Thu, 15 Aug 2024 20:37:54 +0000 (-0400) Subject: optimize asynchronous function invocations; fix for running return from trap while... X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=cf694865de527e597de5a906643a74037341a431;p=thirdparty%2Fbash.git optimize asynchronous function invocations; fix for running return from trap while sourcing a file; restore completion function if read -e is interrupted --- diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 835f2473..e87dec73 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -9929,3 +9929,65 @@ builtins/read.def zungetc to push the delimiter back, adjust mbchar, and return what we read so far to be added as single bytes From a report by Kerin Millar + + 8/7 + --- +builtins/evalstring.c + - can_optimize_connection: only check bash_input.location.string if + bash_input.type == st_string, in case we want to use this in other + contexts. If we do, the caller *must* make sure it's the last + command in the calling context + +execute_cmd.c + - execute_subshell_builtin_or_function: if this is an async function + call, try to optimize away the fork before the last simple command + in the function body by calling optimize_shell_function + - execute_command_internal: if we have a simple command for which + CMD_TRY_OPTIMIZING is set in a SUBSHELL_ASYNC subshell environment, + try to set CMD_NO_FORK by checking via should_optimize_fork + + 8/9 + --- +parse.y + - yy_readline_get: before calling readline, call rl_clear_signals to + reset the signal handling disposition to a known state. Most of the + time it's a no-op + +lib/readline/signals.c + - _rl_handle_signal: make the call to sigprocmask(SIG_UNBLOCK,... + more symmetric with the corresponding call to SIG_BLOCK + +trap.c + - run_pending_traps: before calling run_interrupt_trap, restore + running_trap and trap_return_context, since _run_trap_internal + will save and restore them, too + +builtins/read.def + - read_builtin: if -e is supplied, make sure to install unwind-protects + to reset the attempted completion function and the event hook even + if the timeout is not supplied. + Report from Oguz + + 8/12 + ---- +lib/readline/histsearch.c,lib/readline/histlib.h + - history_search_internal: takes a new argument, LINEDIR, saying which + direction to perform the substring/pattern search in the line, + decoupling it from the direction through the history list; changed + all callers (history_search, history_search_prefix, _hs_history_search, + _hs_history_patsearch) + - _hs_history_search,_hs_history_patsearch: takes the same new LINEDIR + argument, just passes it to history_search_internal; changed all + callers (noninc_search_from_pos) + +lib/readline/search.c + - noninc_search_from_pos: changed calls to _hs_history_search and + _hs_history_patsearch + +lib/readline/histexpand.c + - get_history_event: instead of using function pointers to a history + search function, set the right flags and just call _hs_history_search + with those flags using -1 for list direction and line direction + + + diff --git a/MANIFEST b/MANIFEST index 55a3c41a..2d8b4311 100644 --- a/MANIFEST +++ b/MANIFEST @@ -622,6 +622,8 @@ po/it.gmo f po/it.po f po/ja.gmo f po/ja.po f +po/ka.gmo f +po/ka.po f po/ko.gmo f po/ko.po f po/lt.gmo f diff --git a/builtins/common.h b/builtins/common.h index 41437a33..99684920 100644 --- a/builtins/common.h +++ b/builtins/common.h @@ -216,6 +216,7 @@ extern int parse_and_execute (char *, const char *, int); extern int evalstring (char *, const char *, int); extern void parse_and_execute_cleanup (int); extern int parse_string (char *, const char *, int, COMMAND **, char **); +extern int should_optimize_fork (COMMAND *, int); extern int should_suppress_fork (COMMAND *); extern int can_optimize_connection (COMMAND *); extern int can_optimize_cat_file (COMMAND *); diff --git a/builtins/evalstring.c b/builtins/evalstring.c index 2ea40162..8a9cf2d7 100644 --- a/builtins/evalstring.c +++ b/builtins/evalstring.c @@ -138,7 +138,7 @@ should_suppress_fork (COMMAND *command) int can_optimize_connection (COMMAND *command) { - return (*bash_input.location.string == '\0' && + return ((bash_input.type != st_string || *bash_input.location.string == '\0') && parser_expanding_alias () == 0 && (command->value.Connection->connector == AND_AND || command->value.Connection->connector == OR_OR || command->value.Connection->connector == ';') && command->value.Connection->second->type == cm_simple); diff --git a/execute_cmd.c b/execute_cmd.c index 6fd69602..cda73a78 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -913,6 +913,18 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p begin_unwind_frame ("simple_lineno"); add_unwind_protect (uw_restore_lineno, (void *) (intptr_t) save_line_number); + /* Limit the scope of this attempted optimization for now: async + commands for which TRY_OPTIMIZING is set (see call to optimize_shell_function + for async functions in execute_subshell_builtin_or_function below) + in interactive and script shells. */ + if ((command->flags & CMD_TRY_OPTIMIZING) && + (subshell_environment & SUBSHELL_ASYNC) && startup_state < 2 && + should_optimize_fork (command, 0)) + { + command->flags |= CMD_NO_FORK; + command->value.Simple->flags |= CMD_NO_FORK; + } + SET_LINE_NUMBER (command->value.Simple->line); exec_result = execute_simple_command (command->value.Simple, pipe_in, pipe_out, @@ -5523,6 +5535,8 @@ execute_subshell_builtin_or_function (WORD_LIST *words, REDIRECT *redirects, } else { + if (async) + optimize_shell_function (function_cell (var)); r = execute_function (var, words, flags, fds_to_close, async, 1); fflush (stdout); subshell_exit (r); diff --git a/lib/readline/histexpand.c b/lib/readline/histexpand.c index 21185f9d..db9aa185 100644 --- a/lib/readline/histexpand.c +++ b/lib/readline/histexpand.c @@ -141,7 +141,7 @@ get_history_event (const char *string, int *caller_index, int delimiting_quote) register char c; HIST_ENTRY *entry; int which, sign, local_index, substring_okay; - _hist_search_func_t *search_func; + int search_flags; char *temp; /* The event can be specified in a number of ways. @@ -269,10 +269,10 @@ get_history_event (const char *string, int *caller_index, int delimiting_quote) FAIL_SEARCH (); } - search_func = substring_okay ? history_search : history_search_prefix; + search_flags = substring_okay ? NON_ANCHORED_SEARCH : ANCHORED_SEARCH; while (1) { - local_index = (*search_func) (temp, -1); + local_index = _hs_history_search (temp, -1, -1, search_flags); if (local_index < 0) FAIL_SEARCH (); diff --git a/lib/readline/histlib.h b/lib/readline/histlib.h index da8e6533..d41b4ea1 100644 --- a/lib/readline/histlib.h +++ b/lib/readline/histlib.h @@ -83,8 +83,8 @@ /* internal extern function declarations used by other parts of the library */ /* histsearch.c */ -extern int _hs_history_patsearch (const char *, int, int); -extern int _hs_history_search (const char *, int, int); +extern int _hs_history_patsearch (const char *, int, int, int); +extern int _hs_history_search (const char *, int, int, int); /* history.c */ extern void _hs_replace_history_data (int, histdata_t *, histdata_t *); diff --git a/lib/readline/histsearch.c b/lib/readline/histsearch.c index b43ead1f..36c46996 100644 --- a/lib/readline/histsearch.c +++ b/lib/readline/histsearch.c @@ -1,6 +1,6 @@ /* histsearch.c -- searching the history list. */ -/* Copyright (C) 1989, 1992-2009,2017,2021,2023 Free Software Foundation, Inc. +/* Copyright (C) 1989, 1992-2009,2017,2021-2024 Free Software Foundation, Inc. This file contains the GNU History Library (History), a set of routines for managing the text of previously typed lines. @@ -53,23 +53,25 @@ string. */ char *history_search_delimiter_chars = (char *)NULL; -static int history_search_internal (const char *, int, int); +static int history_search_internal (const char *, int, int, int); /* Search the history for STRING, starting at history_offset. - If DIRECTION < 0, then the search is through previous entries, else - through subsequent. If ANCHORED is non-zero, the string must + If LISTDIR < 0, then the search is through previous entries, else + through subsequent. If ANCHORED is non-zero, the string must appear at the beginning of a history line, otherwise, the string - may appear anywhere in the line. If PATSEARCH is non-zero, and fnmatch(3) - is available, fnmatch is used to match the string instead of a simple - string comparison. If IGNORECASE is set, the string comparison is - performed case-insensitively. If the string is found, then + may appear anywhere in the line. If the search is not anchored, LINEDIR + determines how the line is searched: if it is < 0, the search proceeds + from the end of the line to the beginning, otherwise the substring search + starts at the beginning of each history entry. If PATSEARCH is non-zero, + and fnmatch(3) is available, fnmatch is used to match the string instead + of a simple string comparison. If IGNORECASE is set, the string comparison + is performed case-insensitively. If the string is found, then current_history () is the history entry, and the value of this - function is the offset in the line of that history entry that the - string was found in. Otherwise, nothing is changed, and a -1 is - returned. */ + function is the offset in the line of that history entry in which the + string was found. Otherwise, nothing is changed, and a -1 is returned. */ static int -history_search_internal (const char *string, int direction, int flags) +history_search_internal (const char *string, int listdir, int linedir, int flags) { int i, reverse; char *line; @@ -80,7 +82,7 @@ history_search_internal (const char *string, int direction, int flags) HIST_ENTRY **the_history; /* local */ i = history_offset; - reverse = (direction < 0); + reverse = (listdir < 0); anchored = (flags & ANCHORED_SEARCH); #if defined (HAVE_FNMATCH) patsearch = (flags & PATTERN_SEARCH); @@ -157,7 +159,7 @@ history_search_internal (const char *string, int direction, int flags) } /* Do substring search. */ - if (reverse) + if (linedir < 0) /* search backwards from end */ { size_t ll; @@ -240,7 +242,7 @@ history_search_internal (const char *string, int direction, int flags) } int -_hs_history_patsearch (const char *string, int direction, int flags) +_hs_history_patsearch (const char *string, int listdir, int linedir, int flags) { char *pat; size_t len, start; @@ -289,45 +291,48 @@ _hs_history_patsearch (const char *string, int direction, int flags) pat = string; #endif - ret = history_search_internal (pat, direction, flags|PATTERN_SEARCH); + ret = history_search_internal (pat, listdir, linedir, flags|PATTERN_SEARCH); if (pat != string) xfree (pat); return ret; } -/* Do a non-anchored search for STRING through the history in DIRECTION. */ +/* Do a non-anchored search for STRING through the history list in direction + LISTDIR. */ int -history_search (const char *string, int direction) +history_search (const char *string, int listdir) { - return (history_search_internal (string, direction, NON_ANCHORED_SEARCH)); + return (history_search_internal (string, listdir, listdir, NON_ANCHORED_SEARCH)); } -/* Do an anchored search for string through the history in DIRECTION. */ +/* Do an anchored search for string through the history list in direction + LISTDIR. */ int -history_search_prefix (const char *string, int direction) +history_search_prefix (const char *string, int listdir) { - return (history_search_internal (string, direction, ANCHORED_SEARCH)); + return (history_search_internal (string, listdir, listdir, ANCHORED_SEARCH)); } -/* At some point, make this public for users of the history library. */ +/* Perform a history search for STRING, letting the caller specify the flags. + At some point, make this public for users of the history library. */ int -_hs_history_search (const char *string, int direction, int flags) +_hs_history_search (const char *string, int listdir, int linedir, int flags) { - return (history_search_internal (string, direction, flags)); + return (history_search_internal (string, listdir, linedir, flags)); } -/* Search for STRING in the history list. DIR is < 0 for searching - backwards. POS is an absolute index into the history list at - which point to begin searching. */ +/* Search for STRING in the history list. LISTDIR is < 0 for searching + backwards through the list. POS is an absolute index into the history + list where the search should begin. */ int -history_search_pos (const char *string, int dir, int pos) +history_search_pos (const char *string, int listdir, int pos) { int ret, old; old = where_history (); history_set_pos (pos); - if (history_search (string, dir) == -1) + if (history_search (string, listdir) == -1) { history_set_pos (old); return (-1); diff --git a/lib/readline/search.c b/lib/readline/search.c index 96bb83a5..d7a441e2 100644 --- a/lib/readline/search.c +++ b/lib/readline/search.c @@ -174,12 +174,12 @@ noninc_search_from_pos (char *string, int pos, int dir, int flags, int *ncp) } if (flags & SF_PATTERN) - ret = _hs_history_patsearch (s, dir, sflags); + ret = _hs_history_patsearch (s, dir, dir, sflags); else { if (_rl_search_case_fold) sflags |= CASEFOLD_SEARCH; - ret = _hs_history_search (s, dir, sflags); + ret = _hs_history_search (s, dir, dir, sflags); } RL_UNSETSTATE(RL_STATE_SEARCH); diff --git a/lib/readline/signals.c b/lib/readline/signals.c index 706035e9..a67f6214 100644 --- a/lib/readline/signals.c +++ b/lib/readline/signals.c @@ -279,7 +279,7 @@ _rl_handle_signal (int sig) #if defined (HAVE_POSIX_SIGNALS) /* Unblock any signal(s) blocked above */ if (block_sig) - sigprocmask (SIG_UNBLOCK, &oset, (sigset_t *)NULL); + sigprocmask (SIG_UNBLOCK, &set, &oset); #endif /* We don't have to bother unblocking the signal because we are not diff --git a/parse.y b/parse.y index 1f7527a5..7e9e013e 100644 --- a/parse.y +++ b/parse.y @@ -1621,6 +1621,7 @@ yy_readline_get (void) old_sigint = IMPOSSIBLE_TRAP_HANDLER; if (signal_is_ignored (SIGINT) == 0) { + rl_clear_signals (); /* reset to known state, usually a no-op */ old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler); } diff --git a/trap.c b/trap.c index 32880b77..ae761508 100644 --- a/trap.c +++ b/trap.c @@ -387,6 +387,11 @@ run_pending_traps (void) if (sig == SIGINT) { pending_traps[sig] = 0; /* XXX */ + /* _run_trap_internal saves and restores these, so want + the original values. */ + running_trap = old_running; + trap_return_context = old_context; + /* XXX - bash_trapsig()? */ /* We don't modify evalnest here, since run_interrupt_trap() calls _run_trap_internal, which does. */ run_interrupt_trap (0);