2/1
---
config-top.h
- - DONT_REPORT_SIGPIPE: define, so non-interactive shells will no
+ - DONT_REPORT_SIGTERM: define, so non-interactive shells will no
longer print termination messages for child processes killed by
SIGTERM
configure.ac
- globasciiranges: RRI now on by default, must be turned off explicitly
at configure time or runtime with `shopt -u globasciiranges'
+
+ 8/14
+ ----
+variables.c
+ - dispose_saved_dollar_vars: decrement stack pointer before looking
+ for saved positional parameters to dispose; stack pointer always
+ points to the first unused slot
+
+ 8/15
+ ----
+variables.c
+ - dollar_arg_stack: now a stack of struct saved_dollar_vars, which has
+ an array for the first ten (dollar_vars) and a WORD_LIST * for the
+ remaining (rest_of_args). Fixes performance issue with function calls
+ and large numbers of positional parameters raised by
+ Bize Ma <binaryzebra@gmail.com>
+ - {save,restore,free,free_saved}_dollar_vars: new functions to manage
+ dollar_vars and dollar_arg_stack members. Need to keep these in sync
+ with whatever remember_args does
+ - push_dollar_vars: use save_dollar_vars, which just copies pointers,
+ and directly assign rest_of_args, without copying the words, to the
+ dollar_arg_stack entry. Have to clear dollar_vars and rest_of_args
+ with the assumption that callers will call remember_args(args, 1)
+ immediately following
+ - pop_dollar_vars: free current positional parameters and restore old
+ ones from pointers saved in dollar_arg_stack, making sure to
+ invalidate any cached value for "$@"
+ - dispose_saved_dollar_vars: free saved pointers from current index
+ into dollar_arg_stack
+
+doc/{bash.1,bashref.texi}
+ - POSIXLY_CORRECT: make sure to note that bash makes sure this variable
+ is set when posix mode is enabled
+
+ 8/17
+ ----
+{jobs,nojobs}.c
+ - set_jobs_list_frozen: set jobs_list_frozen to a particular value.
+ Intended to save and restore the value around code sections instead
+ of unconditionally unfreezing it.
+
+jobs.h
+ - set_jobs_list_frozen: extern declaration
+
+execute_cmd.c
+ - execute_pipeline: if lastpipe is enabled, save and restore the
+ value of jobs_list_frozen using freeze_jobs_list/set_jobs_list_frozen
+ to avoid problems with race conditions and nested pipelines
+ causing jobs to be removed from the jobs table. Fixes savannah issue
+ https://savannah.gnu.org/support/index.php?109541 reported by
+ Björn Kautler <vampire0>
tests/varenv12.sub f
tests/varenv13.sub f
tests/varenv14.sub f
+tests/varenv15.sub f
+tests/varenv15.in f
tests/version f
tests/version.mini f
tests/vredir.tests f
typedef RETSIGTYPE sigfunc();
-int nsigint;
+volatile int nsigint;
#ifdef HAVE_POSIX_SIGNALS
sigfunc *
FREE (newval);
VUNSETATTR (entry, att_invisible); /* no longer invisible */
+
+ /* check mark_modified_variables if we ever want to export array vars */
return (entry);
}
typedef RETSIGTYPE sigfunc();
-int nsigint;
+volatile int nsigint;
#ifdef HAVE_POSIX_SIGNALS
sigfunc *
.if t \f(CWset -o posix\fP
.if n \fIset -o posix\fP
had been executed.
+When the shell enters \fIposix mode\fP, it sets this variable if it was
+not already set.
.TP
.B PROMPT_COMMAND
If set, the value is executed as a command prior to issuing each primary
@code{set -o posix}
@end example
@noindent
-had been executed.
+had been executed.
+When the shell enters @sc{posix} mode, it sets this variable if it was
+not already set.
@item PPID
The process @sc{id} of the shell's parent process. This variable
The following list is what's changed when `@sc{posix} mode' is in effect:
@enumerate
+@item
+Bash ensures that the @env{POSIXLY_CORRECT} variable is set.
+
@item
When a command in the hash table no longer exists, Bash will re-search
@env{$PATH} to find the new location. This is also available with
struct fd_bitmap *fds_to_close;
{
int prev, fildes[2], new_bitmap_size, dummyfd, ignore_return, exec_result;
- int lstdin, lastpipe_flag, lastpipe_jid;
+ int lstdin, lastpipe_flag, lastpipe_jid, old_frozen;
COMMAND *cmd;
struct fd_bitmap *fd_bitmap;
pid_t lastpid;
prev = NO_PIPE;
add_unwind_protect (restore_stdin, lstdin);
lastpipe_flag = 1;
- freeze_jobs_list ();
+ old_frozen = freeze_jobs_list ();
lastpipe_jid = stop_pipeline (0, (COMMAND *)NULL); /* XXX */
add_unwind_protect (lastpipe_cleanup, lastpipe_jid);
}
else if (pipefail_opt)
exec_result = exec_result | lstdin; /* XXX */
/* otherwise we use exec_result */
-
#endif
- unfreeze_jobs_list ();
+
+ set_jobs_list_frozen (old_frozen);
}
discard_unwind_frame ("lastpipe-exec");
jobs_list_frozen = 0;
}
+void
+set_jobs_list_frozen (s)
+ int s;
+{
+ jobs_list_frozen = s;
+}
+
/* Allow or disallow job control to take place. Returns the old value
of job_control. */
int
extern void run_sigchld_trap __P((int));
extern int freeze_jobs_list __P((void));
-extern void unfreeze_jobs_list __P((void));
+extern void unfreeeze_jobs_list __P((void));
+extern void set_jobs_list_frozen __P((int));
extern int set_job_control __P((int));
extern void without_job_control __P((void));
extern void end_job_control __P((void));
302 / 1000 is log10 (2) rounded up;
add one for integer division truncation;
add one more for a minus sign if t is signed. */
+#ifndef INT_STRLEN_BOUND
#define INT_STRLEN_BOUND(t) \
((sizeof (t) * CHAR_BIT - TYPE_SIGNED (t)) * 302 / 1000 \
+ 1 + TYPE_SIGNED (t))
+#endif
/* conversion flags */
#define PF_ALTFORM 0x00001 /* # */
{
}
+void
+set_jobs_list_frozen (s)
+ int s;
+{
+}
+
int
count_all_jobs ()
{
declare -a s=([0]="X" [1]="Y")
declare -a a=([0]="XY")
declare -a s=([0]="XY")
+f: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
+f1: after: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+done: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
+f3:1
+f3:2
+f3:3
+f3:4
+f3:5
+f3:6
+f3:7
+f3:8
+f3:9
+f3:10
+f3:11
+f3:12
+f3:13
+f3:14
+f3:15
+f3:16
+f3:17
+f3:18
+f3:19
+f3:20
+before source: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+varenv15.in: before set: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+varenv15.in: after set: a b c d e f g h i j k l m n o p q r s t u v w x y z
+after source 1: a b c d e f g h i j k l m n o p q r s t u v w x y z
+varenv15.in: before set: one two three four five six seven eight nine ten
+varenv15.in: after set: a b c d e f g h i j k l m n o p q r s t u v w x y z
+after source 2: a b c d e f g h i j k l m n o p q r s t u v w x y z
a=z
a=b
a=z
# localvar_inherit
${THIS_SH} ./varenv14.sub
+${THIS_SH} ./varenv15.sub
+
# make sure variable scoping is done right
tt() { typeset a=b;echo a=$a; };a=z;echo a=$a;tt;echo a=$a
--- /dev/null
+echo varenv15.in: before set: "$@"
+set -- a b c d e f g h i j k l m n o p q r s t u v w x y z
+echo varenv15.in: after set: "$@"
--- /dev/null
+# check saving and restoring positional parameters around function calls
+
+f()
+{
+ echo $FUNCNAME: "$@"
+}
+
+f1()
+{
+ f {1..50}
+ echo $FUNCNAME: after: $@
+}
+
+set -- {1..100}
+
+f1 {1..20}
+echo done: $@
+
+f3()
+{
+ echo $FUNCNAME:$1
+ shift
+ if [ $# -le 0 ]; then
+ return
+ fi
+ f3 "$@"
+}
+
+f3 {1..20}
+
+# now let's try source with and without positional parameters
+
+set -- {1..20}
+echo before source: "$@"
+. ./varenv15.in
+echo after source 1: "$@"
+. ./varenv15.in one two three four five six seven eight nine ten
+echo after source 2: "$@"
/* */
/* **************************************************************** */
-static WORD_LIST **dollar_arg_stack = (WORD_LIST **)NULL;
+struct saved_dollar_vars {
+ char **first_ten;
+ WORD_LIST *rest;
+};
+
+static struct saved_dollar_vars *dollar_arg_stack = (struct saved_dollar_vars *)NULL;
static int dollar_arg_stack_slots;
static int dollar_arg_stack_index;
+/* Functions to manipulate dollar_vars array. Need to keep these in sync with
+ whatever remember_args() does. */
+static char **
+save_dollar_vars ()
+{
+ char **ret;
+ int i;
+
+ ret = strvec_create (10);
+ for (i = 1; i < 10; i++)
+ {
+ ret[i] = dollar_vars[i];
+ dollar_vars[i] = (char *)NULL;
+ }
+ return ret;
+}
+
+static void
+restore_dollar_vars (args)
+ char **args;
+{
+ int i;
+
+ for (i = 1; i < 10; i++)
+ dollar_vars[i] = args[i];
+}
+
+static void
+free_dollar_vars ()
+{
+ int i;
+
+ for (i = 1; i < 10; i++)
+ {
+ FREE (dollar_vars[i]);
+ dollar_vars[i] = (char *)NULL;
+ }
+}
+
+static void
+free_saved_dollar_vars (args)
+ char **args;
+{
+ int i;
+
+ for (i = 1; i < 10; i++)
+ FREE (args[i]);
+}
+
/* XXX - should always be followed by remember_args () */
void
push_context (name, is_subshell, tempvars)
{
if (dollar_arg_stack_index + 2 > dollar_arg_stack_slots)
{
- dollar_arg_stack = (WORD_LIST **)
+ dollar_arg_stack = (struct saved_dollar_vars *)
xrealloc (dollar_arg_stack, (dollar_arg_stack_slots += 10)
- * sizeof (WORD_LIST *));
+ * sizeof (struct saved_dollar_vars));
}
- dollar_arg_stack[dollar_arg_stack_index++] = list_rest_of_args ();
- dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+
+ dollar_arg_stack[dollar_arg_stack_index].first_ten = save_dollar_vars ();
+ dollar_arg_stack[dollar_arg_stack_index++].rest = rest_of_args;
+ rest_of_args = (WORD_LIST *)NULL;
+
+ dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
+ dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
}
/* Restore the positional parameters from our stack. */
void
pop_dollar_vars ()
{
- if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+ if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
return;
- remember_args (dollar_arg_stack[--dollar_arg_stack_index], 1);
- dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
- dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+ /* Do what remember_args (xxx, 1) would have done. */
+ free_dollar_vars ();
+ dispose_words (rest_of_args);
+
+ rest_of_args = dollar_arg_stack[--dollar_arg_stack_index].rest;
+ restore_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
+ free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
+
+ dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
+ dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
+
set_dollar_vars_unchanged ();
+ invalidate_cached_quoted_dollar_at ();
}
void
dispose_saved_dollar_vars ()
{
- if (!dollar_arg_stack || dollar_arg_stack_index == 0)
+ if (dollar_arg_stack == 0 || dollar_arg_stack_index == 0)
return;
- dispose_words (dollar_arg_stack[dollar_arg_stack_index]);
- dollar_arg_stack[dollar_arg_stack_index] = (WORD_LIST *)NULL;
+ dispose_words (dollar_arg_stack[--dollar_arg_stack_index].rest);
+ free_saved_dollar_vars (dollar_arg_stack[dollar_arg_stack_index].first_ten);
+ free (dollar_arg_stack[dollar_arg_stack_index].first_ten);
+
+ dollar_arg_stack[dollar_arg_stack_index].first_ten = (char **)NULL;
+ dollar_arg_stack[dollar_arg_stack_index].rest = (WORD_LIST *)NULL;
}
/* Initialize BASH_ARGV and BASH_ARGC after turning on extdebug after the