"wait" loses signals
A bug report from Harald van Dijk: test2.sh: trap 'kill $!; exit' TERM { kill $$; exec sleep 9; } & wait $! The above script ought exit quickly, and not leave a stray "sleep" child: (1) if "kill $$" signal is delivered before "wait", then TERM trap will kill the child, and exit. (2) if "kill $$" signal is delivered to "wait", it must be interrupted by the signal, then TERM trap will kill the child, and exit. The helper to loop the above: test1.sh: i=1 while test "$i" -lt 10; do echo "$i" "$@" test2.sh i=$((i + 1)) done To run: sh test1.sh bash 4.4.23 fails pretty quickly: $ sh test1.sh bash 1 ... 581 _ Under strace, it seems that "wait" enters wait4() syscall and waits for the child. (The fact that the pause is 9 seconds is another hint).
test -v for array does not work as documented
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: x86_64-pc-linux-gnu-gcc Compilation CFLAGS: -march=native -ggdb -O2 -pipe -Wno-parentheses -Wno-format-security uname output: Linux a1i15 4.19.102-gentoo #1 SMP Fri Feb 7 14:32:53 CET 2020 x86_64 Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz GenuineIntel GNU/Linux Machine Type: x86_64-pc-linux-gnu Bash Version: 5.0 Patch Level: 16 Release Status: release Description: The GNU Bash Reference Manual Version 5.0 says about test -v: '-v VARNAME' True if the shell variable VARNAME is set (has been assigned a value). However, it doesn't always return true when VARNAME is an (indexed or associative) array that has been assigned a value. See also Gentoo bug https://bugs.gentoo.org/710076 for some context and additional examples. Repeat-By: $ var1=() $ var2[1]=a $ var3=( b c ) $ declare -A var4; var4["foo"]=d $ declare -p var0 var1 var2 var3 var4 bash: declare: var0: not found declare -a var1=() declare -a var2=([1]="a") declare -a var3=([0]="b" [1]="c") declare -A var4=([foo]="d" ) $ [[ -v var0 ]]; echo $? 1 $ [[ -v var1 ]]; echo $? 1 $ [[ -v var2 ]]; echo $? 1 $ [[ -v var3 ]]; echo $? 0 $ [[ -v var4 ]]; echo $? 1 I would expect 1 only for var0, but 0 for all the others (which have been assigned a value). In fact, bash version 4.2.53 behaves as expected, whereas I get the above result with versions 4.4.23 and 5.0.16.
Re: test -v for array does not work as documented
On 2/19/20 7:00 AM, Ulrich Mueller wrote: > Bash Version: 5.0 > Patch Level: 16 > Release Status: release > > Description: > The GNU Bash Reference Manual Version 5.0 says about test -v: > '-v VARNAME' >True if the shell variable VARNAME is set (has been >assigned a value). > > However, it doesn't always return true when VARNAME is an > (indexed or associative) array that has been assigned a value. If you refer to an array variable without the subscript, it's equivalent to referencing element 0. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: test -v for array does not work as documented
> On Wed, 19 Feb 2020, Chet Ramey wrote: > On 2/19/20 7:00 AM, Ulrich Mueller wrote: >> Bash Version: 5.0 >> Patch Level: 16 >> Release Status: release >> >> Description: >> The GNU Bash Reference Manual Version 5.0 says about test -v: >> '-v VARNAME' >> True if the shell variable VARNAME is set (has been >> assigned a value). >> >> However, it doesn't always return true when VARNAME is an >> (indexed or associative) array that has been assigned a value. > If you refer to an array variable without the subscript, it's equivalent > to referencing element 0. That doesn't seem obvious from the documentation for -v. So, is there any syntax that allows to test if a value has been assigned to the array variable? Especially, to distinguish VARNAME=() (empty array) from VARNAME being unset?
Re: test -v for array does not work as documented
On 19/02/2020 23.18, Ulrich Mueller wrote: > So, is there any syntax that allows to test if a value has been assigned > to the array variable? Especially, to distinguish VARNAME=() (empty > array) from VARNAME being unset? Not `test` as such as we have just learned, but the returncode of `declare -p VARNAME` will be different for VARNAME being unset or being set to `()` or `""`. Add `&>/dev/null` to taste..! Peter
Re: test -v for array does not work as documented
On 2/19/20 11:18 AM, Ulrich Mueller wrote: >> On Wed, 19 Feb 2020, Chet Ramey wrote: > >> On 2/19/20 7:00 AM, Ulrich Mueller wrote: >>> Bash Version: 5.0 >>> Patch Level: 16 >>> Release Status: release >>> >>> Description: >>> The GNU Bash Reference Manual Version 5.0 says about test -v: >>> '-v VARNAME' >>> True if the shell variable VARNAME is set (has been >>> assigned a value). >>> >>> However, it doesn't always return true when VARNAME is an >>> (indexed or associative) array that has been assigned a value. > >> If you refer to an array variable without the subscript, it's equivalent >> to referencing element 0. > > That doesn't seem obvious from the documentation for -v. It's in Arrays: "Referencing an array variable without a subscript is equivalent to ref- erencing the array with a subscript of 0." > So, is there any syntax that allows to test if a value has been assigned > to the array variable? [ -v array[@] ] > Especially, to distinguish VARNAME=() (empty > array) from VARNAME being unset? There's little to distinguish them: neither has a subscript that's been assigned a value. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: test -v for array does not work as documented
2020-02-19 17:18:14 +0100, Ulrich Mueller: [...] > So, is there any syntax that allows to test if a value has been assigned > to the array variable? Especially, to distinguish VARNAME=() (empty > array) from VARNAME being unset? [...] You could do: if typeset -p var 2> /dev/null | grep -q '='; then echo var has a value fi For namerefs, that's whether they are referencing a variable, that variable could still be undeclared (let alone set). -- Stephane
Re: "wait" loses signals
On 2/19/20 5:29 AM, Denys Vlasenko wrote: > A bug report from Harald van Dijk: > > test2.sh: > trap 'kill $!; exit' TERM > { kill $$; exec sleep 9; } & > wait $! > > The above script ought exit quickly, and not leave a stray > "sleep" child: > (1) if "kill $$" signal is delivered before "wait", > then TERM trap will kill the child, and exit. This strikes me as a shaky assumption, dependent on when the shell receives the SIGTERM and when it runs traps. (There's nothing in POSIX that says when pending traps are processed. Bash runs them after commands.) > (2) if "kill $$" signal is delivered to "wait", > it must be interrupted by the signal, > then TERM trap will kill the child, and exit. This is well-defined by POSIX. > > The helper to loop the above: > > test1.sh: > i=1 > while test "$i" -lt 10; do > echo "$i" > "$@" test2.sh > i=$((i + 1)) > done > > To run: sh test1.sh > > bash 4.4.23 fails pretty quickly: > > $ sh test1.sh bash > 1 > ... > 581 > _ It seems inherently racy. I ran this with a lightly-instrumented bash and discovered that signals that arrived when `wait' was running were always processed correctly and killed the process. There were a few times when the signal arrived while `wait' was not running, and some of these cases did not interrupt wait or cause trap execution. Consider this scenario. 1. Bash forks and starts the background process 2. The parent fork returns 3. The parent bash checks for traps, and finds none 4. SIGTERM arrives, the trap signal handler sets a `pending trap' flag for SIGTERM 5. The parent shell runs the `wait' builtin. 6. `wait' is not interrupted by a signal, runs to completion, and the trap runs The window for this is extremely small. I just ran the scripts on RHEL7 and had to go through the loop script multiple times before I saw the 9-second sleep. I saw it more often on Mac OS X, so the scheduler probably plays a role. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Re: test -v for array does not work as documented
On Wed, Feb 19, 2020 at 11:38 AM Ulrich Mueller wrote: > Especially, to distinguish VARNAME=() (empty > array) from VARNAME being unset? I'm not sure if it's intended to work this way, but ${var@a} will report the attributes if the variable has any set, even if it does not have a value, like: [[ ${var@a} == *a* ]] && echo is a declared array This works even for namerefs and indirect references to the variable, like: $ var=(); declare -n ref=var; echo ${ref@a} a $ var=(); ind=var; ${!ind@a} a However, if nounset is enabled, the latter two will trip the "unbound variable" error while using ${var@a} directly will not.
${variable@A} does not work for associative arrays
BASH 5.0.16. $ VAR1=aaa $ declare -a VAR2=(aaa) $ declare -A VAR3=([aaa]=aaa) $ declare -p VAR{1,2,3} declare -- VAR1="aaa" declare -a VAR2=([0]="aaa") declare -A VAR3=([aaa]="aaa" ) $ echo "${VAR1@A}" VAR1='aaa' $ echo "${VAR2@A}" declare -a VAR2='aaa' $ echo "${VAR3@A}" $ -- Arfrever Frehtes Taifersar Arahesis
${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
${!variable@operator} does not work for variables without values. See empty values for all occurrences of ${!var@...} below. ${variable@A} does not work for scalar variables without values, but interestingly ${variable[@]@A} works for them. See difference between ${VAR1@A} and ${VAR1[@]@A} below. However neither ${variable@A} nor ${variable[@]@A} works for arrays without values. Both ${variable@a} and ${variable[@]@a} work for scalar variables without values. However ${variable[@]@a} does not work for arrays without values. See difference between ${VAR3@a} and ${VAR3[@]@a}, and between ${VAR5@a} and ${VAR5[@]@a} below. (BASH 5.0.16.) $ declare -lr VAR1 $ declare -lr VAR2=zzz $ declare -alr VAR3 $ declare -alr VAR4=(zzz) $ declare -Alr VAR5 $ declare -Alr VAR6=([0]=zzz) $ declare -p VAR{1,2,3,4,5,6} declare -rl VAR1 declare -rl VAR2="zzz" declare -arl VAR3 declare -arl VAR4=([0]="zzz") declare -Arl VAR5 declare -Arl VAR6=([0]="zzz" ) $ for operator in Q E P A a ; do for var in VAR{1,2,3,4,5,6} ; do echo "var=${var}" ; eval "echo \"\\\${!var@${operator}}: '\${!${var}@${operator}}'\"" ; eval "echo \"\\\${!var[@]@${operator}}: '\${!${var}[@]@${operator}}'\"" ; eval "echo \"\\\${${var}@${operator}}:'\${${var}@${operator}}'\"" ; eval "echo \"\\\${${var}[@]@${operator}}: '\${${var}[@]@${operator}}'\"" ; echo ; done ; done var=VAR1 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR1@Q}:'' ${VAR1[@]@Q}: '' var=VAR2 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR2@Q}:''zzz'' ${VAR2[@]@Q}: ''zzz'' var=VAR3 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR3@Q}:'' ${VAR3[@]@Q}: '' var=VAR4 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR4@Q}:''zzz'' ${VAR4[@]@Q}: ''zzz'' var=VAR5 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR5@Q}:'' ${VAR5[@]@Q}: '' var=VAR6 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR6@Q}:''zzz'' ${VAR6[@]@Q}: ''zzz'' var=VAR1 ${!var@E}:'' ${!var[@]@E}: '' ${VAR1@E}:'' ${VAR1[@]@E}: '' var=VAR2 ${!var@E}:'' ${!var[@]@E}: '' ${VAR2@E}:'zzz' ${VAR2[@]@E}: 'zzz' var=VAR3 ${!var@E}:'' ${!var[@]@E}: '' ${VAR3@E}:'' ${VAR3[@]@E}: '' var=VAR4 ${!var@E}:'' ${!var[@]@E}: '' ${VAR4@E}:'zzz' ${VAR4[@]@E}: 'zzz' var=VAR5 ${!var@E}:'' ${!var[@]@E}: '' ${VAR5@E}:'' ${VAR5[@]@E}: '' var=VAR6 ${!var@E}:'' ${!var[@]@E}: '' ${VAR6@E}:'zzz' ${VAR6[@]@E}: 'zzz' var=VAR1 ${!var@P}:'' ${!var[@]@P}: '' ${VAR1@P}:'' ${VAR1[@]@P}: '' var=VAR2 ${!var@P}:'' ${!var[@]@P}: '' ${VAR2@P}:'zzz' ${VAR2[@]@P}: 'zzz' var=VAR3 ${!var@P}:'' ${!var[@]@P}: '' ${VAR3@P}:'' ${VAR3[@]@P}: '' var=VAR4 ${!var@P}:'' ${!var[@]@P}: '' ${VAR4@P}:'zzz' ${VAR4[@]@P}: 'zzz' var=VAR5 ${!var@P}:'' ${!var[@]@P}: '' ${VAR5@P}:'' ${VAR5[@]@P}: '' var=VAR6 ${!var@P}:'' ${!var[@]@P}: '' ${VAR6@P}:'zzz' ${VAR6[@]@P}: 'zzz' var=VAR1 ${!var@A}:'' ${!var[@]@A}: '' ${VAR1@A}:'' ${VAR1[@]@A}: 'declare -rl VAR1=''' var=VAR2 ${!var@A}:'' ${!var[@]@A}: '' ${VAR2@A}:'declare -rl VAR2='zzz'' ${VAR2[@]@A}: 'declare -rl VAR2='zzz'' var=VAR3 ${!var@A}:'' ${!var[@]@A}: '' ${VAR3@A}:'' ${VAR3[@]@A}: '' var=VAR4 ${!var@A}:'' ${!var[@]@A}: '' ${VAR4@A}:'declare -arl VAR4='zzz'' ${VAR4[@]@A}: 'declare -arl VAR4=([0]="zzz")' var=VAR5 ${!var@A}:'' ${!var[@]@A}: '' ${VAR5@A}:'' ${VAR5[@]@A}: '' var=VAR6 ${!var@A}:'' ${!var[@]@A}: '' ${VAR6@A}:'declare -Arl VAR6='zzz'' ${VAR6[@]@A}: 'declare -Arl VAR6=([0]="zzz" )' var=VAR1 ${!var@a}:'' ${!var[@]@a}: '' ${VAR1@a}:'rl' ${VAR1[@]@a}: 'rl' var=VAR2 ${!var@a}:'' ${!var[@]@a}: '' ${VAR2@a}:'rl' ${VAR2[@]@a}: 'rl' var=VAR3 ${!var@a}:'' ${!var[@]@a}: '' ${VAR3@a}:'arl' ${VAR3[@]@a}: '' var=VAR4 ${!var@a}:'' ${!var[@]@a}: '' ${VAR4@a}:'arl' ${VAR4[@]@a}: 'arl' var=VAR5 ${!var@a}:'' ${!var[@]@a}: '' ${VAR5@a}:'Arl' ${VAR5[@]@a}: '' var=VAR6 ${!var@a}:'' ${!var[@]@a}: '' ${VAR6@a}:'Arl' ${VAR6[@]@a}: 'Arl' $ -- Arfrever Frehtes Taifersar Arahesis
Inconsistent termination of function when 'local' tries to override read-only variable
When scalar variable is read-only, then calling 'local' for this variable (regardless of presence of value in assignment) is non-fatal and subsequent commands in function are executed. When (indexed or associative) array is read-only, then calling 'local -a' or 'local -A' (without value) for this variable is non-fatal and subsequent commands in function are executed. Trying to set global variable without using 'local' is fatal. Trying to set global variable using 'local -g' is non-fatal. In other cases, function is terminated immediately. (BASH 5.0.16.) $ declare -r VAR1=a $ declare -ar VAR2=(a) $ declare -Ar VAR3=([a]=a) $ f() { local VAR1 VAR2 VAR3 ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local VAR1=b VAR2=b VAR3=b ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local -a VAR1 VAR2 VAR3 ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local -a VAR1=(b) ; echo AAA ; } ; f bash: f: VAR1: readonly variable $ f() { local -a VAR2=(b) ; echo AAA ; } ; f bash: f: VAR2: readonly variable $ f() { local -a VAR3=(b) ; echo AAA ; } ; f bash: f: VAR3: readonly variable $ f() { local -A VAR1 VAR2 VAR3 ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { local -A VAR1=([b]=b) ; echo AAA ; } ; f bash: f: VAR1: readonly variable $ f() { local -A VAR2=([b]=b) ; echo AAA ; } ; f bash: f: VAR2: readonly variable $ f() { local -A VAR3=([b]=b) ; echo AAA ; } ; f bash: f: VAR3: readonly variable $ f() { local -g VAR1= VAR2= VAR3= ; echo AAA ; } ; f bash: local: VAR1: readonly variable bash: local: VAR2: readonly variable bash: local: VAR3: readonly variable AAA $ f() { VAR1= ; echo AAA ; } ; f bash: VAR1: readonly variable $ f() { VAR2= ; echo AAA ; } ; f bash: VAR2: readonly variable $ f() { VAR3= ; echo AAA ; } ; f bash: VAR3: readonly variable $ -- Arfrever Frehtes Taifersar Arahesis
Re: ${variable@A} does not work for associative arrays
On 2/19/20 3:05 PM, Arfrever Frehtes Taifersar Arahesis wrote: > BASH 5.0.16. > > $ VAR1=aaa > $ declare -a VAR2=(aaa) > $ declare -A VAR3=([aaa]=aaa) > $ declare -p VAR{1,2,3} > declare -- VAR1="aaa" > declare -a VAR2=([0]="aaa") > declare -A VAR3=([aaa]="aaa" ) > $ echo "${VAR1@A}" > VAR1='aaa' > $ echo "${VAR2@A}" > declare -a VAR2='aaa' > $ echo "${VAR3@A}" Referring to an array variable without a subscript is equivalent to referencing element 0. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/
Unnecessary space in 'declare -p' and [@]@A for non-empty associative arrays
Notice unnecessary space before closing parenthesis for non-empty associative arrays (VAR5, VAR6) below: $ declare -a VAR1=() VAR2=(a) VAR3=(a b) $ declare -A VAR4=() VAR5=([0]=a) VAR6=([0]=a [1]=b) $ declare -p VAR{1,2,3,4,5,6} declare -a VAR1=() declare -a VAR2=([0]="a") declare -a VAR3=([0]="a" [1]="b") declare -A VAR4=() declare -A VAR5=([0]="a" ) declare -A VAR6=([1]="b" [0]="a" ) $ echo "${VAR1[@]@A}" declare -a VAR1=() $ echo "${VAR2[@]@A}" declare -a VAR2=([0]="a") $ echo "${VAR3[@]@A}" declare -a VAR3=([0]="a" [1]="b") $ echo "${VAR4[@]@A}" declare -A VAR4=() $ echo "${VAR5[@]@A}" declare -A VAR5=([0]="a" ) $ echo "${VAR6[@]@A}" declare -A VAR6=([1]="b" [0]="a" ) $ (BASH 5.0.16) -- Arfrever Frehtes Taifersar Arahesis
Re: ${variable@A} does not work for associative arrays
On 2/19/20 3:05 PM, Arfrever Frehtes Taifersar Arahesis wrote: > BASH 5.0.16. > > $ VAR1=aaa > $ declare -a VAR2=(aaa) > $ declare -A VAR3=([aaa]=aaa) > $ declare -p VAR{1,2,3} > declare -- VAR1="aaa" > declare -a VAR2=([0]="aaa") > declare -A VAR3=([aaa]="aaa" ) > $ echo "${VAR1@A}" > VAR1='aaa' > $ echo "${VAR2@A}" > declare -a VAR2='aaa' Well, that looks a bit off. $ VAR2=(aaa ) $ echo "${VAR2@A}" declare -a VAR2='aaa' $ echo "${VAR2[@]@A}" declare -a VAR2=([0]="aaa" [1]="") I suggest next time, do your tests with a multi-element indexed array, since it will make it obvious when your test case is incorrectly printing only one element. > $ echo "${VAR3@A}" > > $ > > -- > Arfrever Frehtes Taifersar Arahesis > -- Eli Schwartz Bug Wrangler and Trusted User signature.asc Description: OpenPGP digital signature
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
> ${variable@A} does not work for scalar variables without values, but > interestingly ${variable[@]@A} works for them. More precisely, ${variable[@]@A} is non-empty, but not exactly correct. > See difference between ${VAR1@A} and ${VAR1[@]@A} below. ${VAR1[@]@A} is: declare -rl VAR1=''" But should be: declare -rl VAR1 As in output of 'declare -p VAR1'. -- Arfrever Frehtes Taifersar Arahesis
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
While described problems exist, there were typos in original reproduction steps. Corrected output also reveals another bug: ${!variable[@]@A} for (indexed or associative) arrays does not include indexes. Example part of output: var=VAR4 ${!var@A}:'declare -arl VAR4='zzz'' ${!var[@]@A}: 'declare -arl VAR4='zzz'' ${VAR4@A}:'declare -arl VAR4='zzz'' ${VAR4[@]@A}: 'declare -arl VAR4=([0]="zzz")' ${!var[@]@A} would be expected to be the same as ${VAR4[@]@A}. Corrected full reproduction steps with better formatting of 'for' loops: $ declare -lr VAR1 $ declare -lr VAR2=zzz $ declare -alr VAR3 $ declare -alr VAR4=(zzz) $ declare -Alr VAR5 $ declare -Alr VAR6=([0]=zzz) $ declare -p VAR{1,2,3,4,5,6} declare -rl VAR1 declare -rl VAR2="zzz" declare -arl VAR3 declare -arl VAR4=([0]="zzz") declare -Arl VAR5 declare -Arl VAR6=([0]="zzz" ) $ for operator in Q E P A a ; do > for var in VAR{1,2,3,4,5,6} ; do > echo "var=${var}" > eval "echo \"\\\${!var@${operator}}:'\${!var@${operator}}'\"" > eval "echo \"\\\${!var[@]@${operator}}: '\${!var[@]@${operator}}'\"" > eval "echo \"\\\${${var}@${operator}}:'\${${var}@${operator}}'\"" > eval "echo \"\\\${${var}[@]@${operator}}: '\${${var}[@]@${operator}}'\"" > echo > done > done var=VAR1 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR1@Q}:'' ${VAR1[@]@Q}: '' var=VAR2 ${!var@Q}:''zzz'' ${!var[@]@Q}: ''zzz'' ${VAR2@Q}:''zzz'' ${VAR2[@]@Q}: ''zzz'' var=VAR3 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR3@Q}:'' ${VAR3[@]@Q}: '' var=VAR4 ${!var@Q}:''zzz'' ${!var[@]@Q}: ''zzz'' ${VAR4@Q}:''zzz'' ${VAR4[@]@Q}: ''zzz'' var=VAR5 ${!var@Q}:'' ${!var[@]@Q}: '' ${VAR5@Q}:'' ${VAR5[@]@Q}: '' var=VAR6 ${!var@Q}:''zzz'' ${!var[@]@Q}: ''zzz'' ${VAR6@Q}:''zzz'' ${VAR6[@]@Q}: ''zzz'' var=VAR1 ${!var@E}:'' ${!var[@]@E}: '' ${VAR1@E}:'' ${VAR1[@]@E}: '' var=VAR2 ${!var@E}:'zzz' ${!var[@]@E}: 'zzz' ${VAR2@E}:'zzz' ${VAR2[@]@E}: 'zzz' var=VAR3 ${!var@E}:'' ${!var[@]@E}: '' ${VAR3@E}:'' ${VAR3[@]@E}: '' var=VAR4 ${!var@E}:'zzz' ${!var[@]@E}: 'zzz' ${VAR4@E}:'zzz' ${VAR4[@]@E}: 'zzz' var=VAR5 ${!var@E}:'' ${!var[@]@E}: '' ${VAR5@E}:'' ${VAR5[@]@E}: '' var=VAR6 ${!var@E}:'zzz' ${!var[@]@E}: 'zzz' ${VAR6@E}:'zzz' ${VAR6[@]@E}: 'zzz' var=VAR1 ${!var@P}:'' ${!var[@]@P}: '' ${VAR1@P}:'' ${VAR1[@]@P}: '' var=VAR2 ${!var@P}:'zzz' ${!var[@]@P}: 'zzz' ${VAR2@P}:'zzz' ${VAR2[@]@P}: 'zzz' var=VAR3 ${!var@P}:'' ${!var[@]@P}: '' ${VAR3@P}:'' ${VAR3[@]@P}: '' var=VAR4 ${!var@P}:'zzz' ${!var[@]@P}: 'zzz' ${VAR4@P}:'zzz' ${VAR4[@]@P}: 'zzz' var=VAR5 ${!var@P}:'' ${!var[@]@P}: '' ${VAR5@P}:'' ${VAR5[@]@P}: '' var=VAR6 ${!var@P}:'zzz' ${!var[@]@P}: 'zzz' ${VAR6@P}:'zzz' ${VAR6[@]@P}: 'zzz' var=VAR1 ${!var@A}:'' ${!var[@]@A}: '' ${VAR1@A}:'' ${VAR1[@]@A}: 'declare -rl VAR1=''' var=VAR2 ${!var@A}:'declare -rl VAR2='zzz'' ${!var[@]@A}: 'declare -rl VAR2='zzz'' ${VAR2@A}:'declare -rl VAR2='zzz'' ${VAR2[@]@A}: 'declare -rl VAR2='zzz'' var=VAR3 ${!var@A}:'' ${!var[@]@A}: '' ${VAR3@A}:'' ${VAR3[@]@A}: '' var=VAR4 ${!var@A}:'declare -arl VAR4='zzz'' ${!var[@]@A}: 'declare -arl VAR4='zzz'' ${VAR4@A}:'declare -arl VAR4='zzz'' ${VAR4[@]@A}: 'declare -arl VAR4=([0]="zzz")' var=VAR5 ${!var@A}:'' ${!var[@]@A}: '' ${VAR5@A}:'' ${VAR5[@]@A}: '' var=VAR6 ${!var@A}:'declare -Arl VAR6='zzz'' ${!var[@]@A}: 'declare -Arl VAR6='zzz'' ${VAR6@A}:'declare -Arl VAR6='zzz'' ${VAR6[@]@A}: 'declare -Arl VAR6=([0]="zzz" )' var=VAR1 ${!var@a}:'' ${!var[@]@a}: '' ${VAR1@a}:'rl' ${VAR1[@]@a}: 'rl' var=VAR2 ${!var@a}:'rl' ${!var[@]@a}: 'rl' ${VAR2@a}:'rl' ${VAR2[@]@a}: 'rl' var=VAR3 ${!var@a}:'' ${!var[@]@a}: '' ${VAR3@a}:'arl' ${VAR3[@]@a}: '' var=VAR4 ${!var@a}:'arl' ${!var[@]@a}: 'arl' ${VAR4@a}:'arl' ${VAR4[@]@a}: 'arl' var=VAR5 ${!var@a}:'' ${!var[@]@a}: '' ${VAR5@a}:'Arl' ${VAR5[@]@a}: '' var=VAR6 ${!var@a}:'Arl' ${!var[@]@a}: 'Arl' ${VAR6@a}:'Arl' ${VAR6[@]@a}: 'Arl' $ -- Arfrever Frehtes Taifersar Arahesis
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
On 2/19/20 6:18 PM, Arfrever Frehtes Taifersar Arahesis wrote: > While described problems exist, there were typos in original reproduction > steps. > > Corrected output also reveals another bug: > ${!variable[@]@A} for (indexed or associative) arrays does not include > indexes. Your examples are all (still) broken. Do not try to reproduce bugs using: VAR1=(aaa) Instead, use: VAR1=(aaa bbb) Reformulate all test cases where you expect the bbb to be printed, but it isn't. $ VAR1=(aaa bbb) $ ref=VAR1 $ echo "${!ref[@]}" 0 $ echo "${!ref[@]@A}" declare -a VAR2='aaa' $ ref2=VAR1[@] $ args() { printf '<%s> ' "$@"; printf \\n; } $ args "${!ref2}" $ args "${!ref2@A}" <> You cannot use ${!ref[@]}, you need the array subscript as part of the set value of "ref" and then indirectly refer to ref. $ declare -A VAR2=([foo]=bar [baz]="how interesting") $ args "${!VAR2[@]}" From man bash: ``` ${!name[@]} ${!name[*]} List of array keys. If name is an array variable, expands to the list of array indices (keys) assigned in name. If name is not an array, expands to 0 if name is set and null otherwise. When @ is used and the expansion appears within double quotes, each key expands to a separate word. ``` And, as predicted, if instead of using ${!ref[@]} you use ${!varname[@]}, you get meaningful information. If you try to look at the array keys of "ref" itself, all it prints is the number 0, because: ref=VAR1 and since it is set and non-null... -- Eli Schwartz Arch Linux Bug Wrangler and Trusted User signature.asc Description: OpenPGP digital signature
Re: "wait" loses signals
On 19/02/2020 20:30, Chet Ramey wrote: On 2/19/20 5:29 AM, Denys Vlasenko wrote: A bug report from Harald van Dijk: test2.sh: trap 'kill $!; exit' TERM { kill $$; exec sleep 9; } & wait $! The above script ought exit quickly, and not leave a stray "sleep" child: (1) if "kill $$" signal is delivered before "wait", then TERM trap will kill the child, and exit. This strikes me as a shaky assumption, dependent on when the shell receives the SIGTERM and when it runs traps. (There's nothing in POSIX that says when pending traps are processed. Bash runs them after commands.) The bash documentation says traps will not be executed until the command completes if it receives a signal while waiting for the command to complete, but it does not say the same for when it receives a signal before waiting for a command to complete. This may be an oversight in the documentation. POSIX says in the description of the trap command "Otherwise, the argument action shall be read and executed by the shell when one of the corresponding conditions arises." Because it says "when", not "after", if interpreted literally, it does not even allow waiting until the current command finishes executing. I realise that that is definitely not the way it is meant to be interpreted, but I am not sure what is. I consider the assumption that the test script is supposed to work a reasonable one, but it is possible that this is considered strictly a QoI issue. But to be clear, regardless of what POSIX requires, I was less concerned with prodding other shell authors into changing their shells and more with seeing what I can do in my shell. I want to have a shell that is capable of handling scripts like this, but it is fine with me if other shells do not share that as a goal. Thanks for looking into this despite your scepticism on the validity of the test. Your description of what happens in bash when this ends up sleeping probably applies to all shells that behave the same way. Cheers, Harald van Dijk
Re: ${!variable@operator} does not work for variables without values; inconsistencies between present and absent [@] for @A and @a
Eli Schwartz 2020-02-20 23:49 UTC: > Your examples are all (still) broken. This would affect only 10 examples from 120, so only 8.33 % of examples, far from all examples. > You cannot use ${!ref[@]}, you need the array subscript as part of the > set value of "ref" and then indirectly refer to ref. > > $ declare -A VAR2=([foo]=bar [baz]="how interesting") > $ args "${!VAR2[@]}" > > ... > And, as predicted, if instead of using ${!ref[@]} you use > ${!varname[@]}, you get meaningful information. But I am not interested in any ${!varname[@]}, but instead in applying @operator transformations. >From `man bash`: ``` ${parameter@operator} Parameter transformation. The expansion is either a transformation of the value of parameter or information about parameter itself, de‐ pending on the value of operator. Each operator is a single letter: Q The expansion is a string that is the value of parameter quoted in a format that can be reused as input. E The expansion is a string that is the value of parameter with backslash escape sequences expanded as with the $'...' quoting mecha‐ nism. P The expansion is a string that is the result of expanding the value of parameter as if it were a prompt string (see PROMPTING be‐ low). A The expansion is a string in the form of an assignment statement or declare command that, if evaluated, will recreate parameter with its attributes and value. a The expansion is a string consisting of flag values representing parameter's attributes. If parameter is @ or *, the operation is applied to each positional parameter in turn, and the expansion is the resultant list. If parame‐ ter is an array variable subscripted with @ or *, the operation is applied to each member of the array in turn, and the expansion is the resultant list. ``` Is there any way for using ${!variable} combined with ${variable@operator} to get useful results for multi-elemental arrays? If not, then I can still use `eval` :) . $ ARRAY=(あ い う え お) $ REF=ARRAY $ eval "echo \"\${${REF}[@]@A}\"" declare -a ARRAY=([0]="あ" [1]="い" [2]="う" [3]="え" [4]="お") $ eval "echo \"\${${REF}[@]@a}\"" a a a a a $ echo "${ARRAY[@]@A}" declare -a ARRAY=([0]="あ" [1]="い" [2]="う" [3]="え" [4]="お") $ echo "${ARRAY[@]@a}" a a a a a $ Majority (3 of 4) of bugs reported by me in this thread are unaffected by above discussion about ${!...} and are certainly still valid. -- Arfrever Frehtes Taifersar Arahesis
Re: "wait" loses signals
Date:Wed, 19 Feb 2020 23:53:56 + From:Harald van Dijk Message-ID: <9b9d435b-3d2f-99bd-eb3d-4a676ce89...@gigawatt.nl> | POSIX says in the description of the trap command "Otherwise, the | argument action shall be read and executed by the shell when one of the | corresponding conditions arises." Because it says "when", not "after", | if interpreted literally, it does not even allow waiting until the | current command finishes executing. You need to look at XCU 2.11 not just the description of the trap command itself. kre