optimize asynchronous function invocations; fix for running return from trap while sourcing a file; restore completion function if read -e is interrupted

This commit is contained in:
Chet Ramey
2024-08-15 16:37:54 -04:00
parent 772e7e760e
commit cf694865de
12 changed files with 129 additions and 39 deletions
+62
View File
@@ -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 <kfm@plushkava.net>
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 <oguzismailuysal@gmail.com>
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
+2
View File
@@ -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
+1
View File
@@ -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 *);
+1 -1
View File
@@ -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);
+14
View File
@@ -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);
+3 -3
View File
@@ -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 ();
+2 -2
View File
@@ -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 *);
+35 -30
View File
@@ -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);
+2 -2
View File
@@ -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);
+1 -1
View File
@@ -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
+1
View File
@@ -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);
}
+5
View File
@@ -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);