reap and store status of process substitutions even when there are no jobs; fix issue with optimizing shell functions that set RETURN trap; fix issue with procsubs and eval allowing '<file'; fix for fignore and ignorning completions

This commit is contained in:
Chet Ramey
2024-07-11 12:03:23 -04:00
parent a91b8b0773
commit d3e86e66ce
13 changed files with 1222 additions and 1810 deletions
+43
View File
@@ -9758,4 +9758,47 @@ lib/readline/search.c
oldpos if the history search is successful; we want the history offset
to be set to the position of the last matching line, like isearch
7/5
---
jobs.c
- procsub_reap: new function, blocks and unblocks SIGCHLD around
call to procsub_prune
- cleanup_dead_jobs: call procsub_reap even if there are no jobs in
the jobs list or the jobs list is frozen
Inspired by report from Zachary Santer <zsanter@gmail.com>
7/6
---
subst.c,subst.h,execute_cmd.c,jobs.c
- reap_procsubs: rename to delete_procsubs
7/7
---
aclocal.m4
- BASH_CHECK_LIB_TERMCAP: check for ncursesw before ncurses, add
-lncursesw if found, to avoid pkgconfig issues for readline (since
this is a shared file)
Report and fix from Rosen Penev <rosenp@gmail.com>
7/8
---
builtins/evalstring.c
- should_optimize_fork: don't optimize the fork if we're executing in
a shell function and a return trap is set
- optimize_shell_function: mark a simple command at the end of a shell
function as a candidate for optimization, rather than setting
CMD_NO_FORK before the function executes -- it could set a return
trap
Report from Jens Schmidt <farblos@vodafonemail.de>
- parse_and_execute: don't let process substitutions or other calls
to parse_and_execute do <file; that should be reserved for command
substitutions and implemented in command_substitute
Report by Emanuele Torre <torreemanuele6@gmail.com>
- parse_string: if flags & SEVAL_ONECMD, stop after parsing a single
command, even if it doesn't consume the entire string
parse.y
- parse_string_to_command: call parse_string with SEVAL_ONECMD, since
we only want to parse a single command and make sure it consumes
the entire string, not consume the string and return the last command
parsed
Vendored
+5 -2
View File
@@ -935,8 +935,8 @@ AC_CACHE_VAL(bash_cv_termcap_lib,
[AC_CHECK_LIB(termcap, tgetent, bash_cv_termcap_lib=libtermcap,
[AC_CHECK_LIB(tinfo, tgetent, bash_cv_termcap_lib=libtinfo,
[AC_CHECK_LIB(curses, tgetent, bash_cv_termcap_lib=libcurses,
[AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
[AC_CHECK_LIB(ncursesw, tgetent, bash_cv_termcap_lib=libncursesw,
[AC_CHECK_LIB(ncursesw, tgetent, bash_cv_termcap_lib=libncursesw,
[AC_CHECK_LIB(ncurses, tgetent, bash_cv_termcap_lib=libncurses,
bash_cv_termcap_lib=gnutermcap)])])])])])])
if test "X$_bash_needmsg" = "Xyes"; then
AC_MSG_CHECKING(which library has the termcap functions)
@@ -952,6 +952,9 @@ TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libtinfo; then
TERMCAP_LIB=-ltinfo
TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncursesw; then
TERMCAP_LIB=-lncursesw
TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncurses; then
TERMCAP_LIB=-lncurses
TERMCAP_DEP=
+12 -4
View File
@@ -109,6 +109,7 @@ should_optimize_fork (COMMAND *command, int subshell)
command->type == cm_simple &&
signal_is_trapped (EXIT_TRAP) == 0 &&
signal_is_trapped (ERROR_TRAP) == 0 &&
(variable_context == 0 || signal_is_trapped (RETURN_TRAP) == 0) &&
any_signals_trapped () < 0 &&
(subshell || (command->redirects == 0 && command->value.Simple->redirects == 0)) &&
((command->flags & CMD_TIME_PIPELINE) == 0) &&
@@ -187,11 +188,11 @@ optimize_shell_function (COMMAND *command)
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))
else if (fc->type == cm_connection && can_optimize_connection (fc))
{
fc->value.Connection->second->flags |= CMD_NO_FORK;
fc->value.Connection->second->value.Simple->flags |= CMD_NO_FORK;
}
fc->value.Connection->second->flags |= CMD_TRY_OPTIMIZING;
fc->value.Connection->second->value.Simple->flags |= CMD_TRY_OPTIMIZING;
}
}
int
@@ -547,17 +548,20 @@ parse_and_execute (char *string, const char *from_file, int flags)
if ((subshell_environment & SUBSHELL_COMSUB) || executing_funsub)
expand_aliases = expaliases_flag;
#if 0
/* See if this is a candidate for $( <file ). */
if (startup_state == 2 &&
(subshell_environment & SUBSHELL_COMSUB) &&
*bash_input.location.string == '\0' &&
can_optimize_cat_file (command))
{
itrace("parse_and_execute: calling cat_file, parse_and_execute_level = %d", parse_and_execute_level);
int r;
r = cat_file (command->value.Simple->redirects);
last_result = (r < 0) ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
}
else
#endif
last_result = execute_command_internal
(command, 0, NO_PIPE, NO_PIPE, bitmap);
dispose_command (command);
@@ -700,6 +704,10 @@ parse_string (char *string, const char *from_file, int flags, COMMAND **cmdp, ch
else
dispose_command (global_command);
global_command = (COMMAND *)NULL;
/* Presumably this is an error if we haven't consumed the
entire string, but we let the caller deal with it. */
if (flags & SEVAL_ONECMD)
break;
}
else
{
Vendored
+109 -103
View File
@@ -1,5 +1,5 @@
#! /bin/sh
# From configure.ac for Bash 5.3, version 5.066.
# From configure.ac for Bash 5.3, version 5.067.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.72 for bash 5.3-alpha.
#
@@ -5599,53 +5599,6 @@ printf "%s\n" "$ac_cv_lib_curses_tgetent" >&6; }
if test "x$ac_cv_lib_curses_tgetent" = xyes
then :
bash_cv_termcap_lib=libcurses
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncurses" >&5
printf %s "checking for tgetent in -lncurses... " >&6; }
if test ${ac_cv_lib_ncurses_tgetent+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lncurses $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char tgetent (void);
int
main (void)
{
return tgetent ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_ncurses_tgetent=yes
else case e in #(
e) ac_cv_lib_ncurses_tgetent=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_tgetent" >&5
printf "%s\n" "$ac_cv_lib_ncurses_tgetent" >&6; }
if test "x$ac_cv_lib_ncurses_tgetent" = xyes
then :
bash_cv_termcap_lib=libncurses
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncursesw" >&5
printf %s "checking for tgetent in -lncursesw... " >&6; }
@@ -5693,6 +5646,53 @@ printf "%s\n" "$ac_cv_lib_ncursesw_tgetent" >&6; }
if test "x$ac_cv_lib_ncursesw_tgetent" = xyes
then :
bash_cv_termcap_lib=libncursesw
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncurses" >&5
printf %s "checking for tgetent in -lncurses... " >&6; }
if test ${ac_cv_lib_ncurses_tgetent+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lncurses $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char tgetent (void);
int
main (void)
{
return tgetent ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_ncurses_tgetent=yes
else case e in #(
e) ac_cv_lib_ncurses_tgetent=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_tgetent" >&5
printf "%s\n" "$ac_cv_lib_ncurses_tgetent" >&6; }
if test "x$ac_cv_lib_ncurses_tgetent" = xyes
then :
bash_cv_termcap_lib=libncurses
else case e in #(
e) bash_cv_termcap_lib=gnutermcap ;;
esac
@@ -5732,6 +5732,9 @@ TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libtinfo; then
TERMCAP_LIB=-ltinfo
TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncursesw; then
TERMCAP_LIB=-lncursesw
TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncurses; then
TERMCAP_LIB=-lncurses
TERMCAP_DEP=
@@ -9197,8 +9200,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
LIBS=$save_LIBS
test $gl_pthread_api = yes && break
done
echo "$as_me:9200: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9201: LIBPTHREAD=$LIBPTHREAD" >&5
echo "$as_me:9203: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9204: LIBPTHREAD=$LIBPTHREAD" >&5
gl_pthread_in_glibc=no
# On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9224,7 +9227,7 @@ rm -rf conftest*
;;
esac
echo "$as_me:9227: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
echo "$as_me:9230: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
# Test for libpthread by looking for pthread_kill. (Not pthread_self,
# since it is defined as a macro on OSF/1.)
@@ -9402,7 +9405,7 @@ fi
fi
fi
echo "$as_me:9405: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
echo "$as_me:9408: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -9649,8 +9652,8 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
LIBS=$save_LIBS
test $gl_pthread_api = yes && break
done
echo "$as_me:9652: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9653: LIBPTHREAD=$LIBPTHREAD" >&5
echo "$as_me:9655: gl_pthread_api=$gl_pthread_api" >&5
echo "$as_me:9656: LIBPTHREAD=$LIBPTHREAD" >&5
gl_pthread_in_glibc=no
# On Linux with glibc >= 2.34, libc contains the fully functional
@@ -9676,7 +9679,7 @@ rm -rf conftest*
;;
esac
echo "$as_me:9679: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
echo "$as_me:9682: gl_pthread_in_glibc=$gl_pthread_in_glibc" >&5
# Test for libpthread by looking for pthread_kill. (Not pthread_self,
# since it is defined as a macro on OSF/1.)
@@ -9854,7 +9857,7 @@ fi
fi
fi
echo "$as_me:9857: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
echo "$as_me:9860: LIBPMULTITHREAD=$LIBPMULTITHREAD" >&5
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether POSIX threads API is available" >&5
printf %s "checking whether POSIX threads API is available... " >&6; }
@@ -22690,53 +22693,6 @@ printf "%s\n" "$ac_cv_lib_curses_tgetent" >&6; }
if test "x$ac_cv_lib_curses_tgetent" = xyes
then :
bash_cv_termcap_lib=libcurses
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncurses" >&5
printf %s "checking for tgetent in -lncurses... " >&6; }
if test ${ac_cv_lib_ncurses_tgetent+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lncurses $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char tgetent (void);
int
main (void)
{
return tgetent ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_ncurses_tgetent=yes
else case e in #(
e) ac_cv_lib_ncurses_tgetent=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_tgetent" >&5
printf "%s\n" "$ac_cv_lib_ncurses_tgetent" >&6; }
if test "x$ac_cv_lib_ncurses_tgetent" = xyes
then :
bash_cv_termcap_lib=libncurses
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncursesw" >&5
printf %s "checking for tgetent in -lncursesw... " >&6; }
@@ -22784,6 +22740,53 @@ printf "%s\n" "$ac_cv_lib_ncursesw_tgetent" >&6; }
if test "x$ac_cv_lib_ncursesw_tgetent" = xyes
then :
bash_cv_termcap_lib=libncursesw
else case e in #(
e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for tgetent in -lncurses" >&5
printf %s "checking for tgetent in -lncurses... " >&6; }
if test ${ac_cv_lib_ncurses_tgetent+y}
then :
printf %s "(cached) " >&6
else case e in #(
e) ac_check_lib_save_LIBS=$LIBS
LIBS="-lncurses $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply.
The 'extern "C"' is for builds by C++ compilers;
although this is not generally supported in C code supporting it here
has little cost and some practical benefit (sr 110532). */
#ifdef __cplusplus
extern "C"
#endif
char tgetent (void);
int
main (void)
{
return tgetent ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_ncurses_tgetent=yes
else case e in #(
e) ac_cv_lib_ncurses_tgetent=no ;;
esac
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS ;;
esac
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_tgetent" >&5
printf "%s\n" "$ac_cv_lib_ncurses_tgetent" >&6; }
if test "x$ac_cv_lib_ncurses_tgetent" = xyes
then :
bash_cv_termcap_lib=libncurses
else case e in #(
e) bash_cv_termcap_lib=gnutermcap ;;
esac
@@ -22823,6 +22826,9 @@ TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libtinfo; then
TERMCAP_LIB=-ltinfo
TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncursesw; then
TERMCAP_LIB=-lncursesw
TERMCAP_DEP=
elif test $bash_cv_termcap_lib = libncurses; then
TERMCAP_LIB=-lncurses
TERMCAP_DEP=
+1 -1
View File
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_REVISION([for Bash 5.3, version 5.066])dnl
AC_REVISION([for Bash 5.3, version 5.067])dnl
define(bashvers, 5.3)
define(relstatus, alpha)
+1 -1
View File
@@ -821,7 +821,7 @@ execute_command_internal (COMMAND *command, int asynchronous, int pipe_in, int p
#if defined (PROCESS_SUBSTITUTION)
# if !defined (HAVE_DEV_FD)
reap_procsubs ();
delete_procsubs (); /* closes fds or unlinks fifos */
# endif
/* XXX - also if sourcelevel != 0? */
+23 -3
View File
@@ -1181,6 +1181,17 @@ procsub_prune (void)
p = ps;
}
}
void
procsub_reap (void)
{
int os;
QUEUE_SIGCHLD(os);
procsub_prune ();
last_procsub_child = (PROCESS *)NULL;
UNQUEUE_SIGCHLD (os);
}
#endif
/* Reset the values of js.j_lastj and js.j_firstj after one or both have
@@ -1233,8 +1244,15 @@ cleanup_dead_jobs (void)
register int i;
int os;
/* Even if the jobs list is frozen or there aren't any background jobs,
clean up any terminated process substitutions. */
if (js.j_jobslots == 0 || jobs_list_frozen)
return;
{
#if defined (PROCESS_SUBSTITUTION)
procsub_reap ();
#endif
return;
}
QUEUE_SIGCHLD(os);
@@ -1255,6 +1273,7 @@ cleanup_dead_jobs (void)
}
#if defined (PROCESS_SUBSTITUTION)
/* Don't need to call procsub_reap() since SIGCHLD is already blocked. */
procsub_prune ();
last_procsub_child = (PROCESS *)NULL;
#endif
@@ -2681,7 +2700,7 @@ wait_for_single_pid (pid_t pid, int flags)
/* If running in posix mode, remove the job from the jobs table immediately */
if (posixly_correct)
{
cleanup_dead_jobs ();
cleanup_dead_jobs (); /* calls procsub_prune */
bgp_delete (pid);
}
@@ -2751,7 +2770,7 @@ wait_for_background_pids (struct procstat *ps)
#if defined (PROCESS_SUBSTITUTION)
if (last_procsub_child && last_procsub_child->pid != NO_PID && last_procsub_child->pid == last_asynchronous_pid)
procsub_waitpid (last_procsub_child->pid);
reap_procsubs (); /* closes fd */
delete_procsubs (); /* closes fds or unlinks fifos */
#endif
/* POSIX.2 says the shell can discard the statuses of all completed jobs if
@@ -3974,6 +3993,7 @@ itrace("waitchld: waitpid returns %d block = %d children_exited = %d", pid, bloc
is blocked. We only use this as a hint that we can remove FIFOs
or close file descriptors corresponding to terminated process
substitutions. */
/* XXX - should combine this list with procsub_add, etc. */
if ((ind = find_procsub_child (pid)) >= 0)
set_procsub_status (ind, pid, WSTATUS (status));
#endif
+1
View File
@@ -256,6 +256,7 @@ extern int procsub_waitpid (pid_t);
extern void procsub_waitall (void);
extern void procsub_clear (void);
extern void procsub_prune (void);
extern void procsub_reap (void);
extern void delete_job (int, int);
extern void nohup_job (int);
+1 -1
View File
@@ -4781,7 +4781,7 @@ parse_string_to_command (char *string, int flags)
/*itrace("parse_string_to_command: size = %d shell_input_line = `%s' string=`%s'", shell_input_line_size, shell_input_line, string);*/
sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE;
sflags = SEVAL_NONINT|SEVAL_NOHIST|SEVAL_NOFREE|SEVAL_ONECMD;
if (flags & SX_NOLONGJMP)
sflags |= SEVAL_NOLONGJMP;
BIN
View File
Binary file not shown.
+1023 -1692
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -6089,7 +6089,7 @@ reap_some_procsubs (int max)
}
void
reap_procsubs (void)
delete_procsubs (void)
{
reap_some_procsubs (nfifo);
}
@@ -6322,7 +6322,7 @@ reap_some_procsubs (int max)
}
void
reap_procsubs (void)
delete_procsubs (void)
{
reap_some_procsubs (totfds);
}
+1 -1
View File
@@ -308,7 +308,7 @@ extern int find_procsub_child (pid_t);
extern void set_procsub_status (int, pid_t, int);
extern void wait_procsubs (void);
extern void reap_procsubs (void);
extern void delete_procsubs (void);
#endif
extern WORD_LIST *list_string_with_quotes (char *);