mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-30 17:09:50 +02:00
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:
@@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user