"wait" loses signals

2020-02-19 Thread Denys Vlasenko

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

2020-02-19 Thread Ulrich Mueller
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

2020-02-19 Thread Chet Ramey
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

2020-02-19 Thread Ulrich Mueller
> 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

2020-02-19 Thread pepa65
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

2020-02-19 Thread Chet Ramey
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 Thread Stephane Chazelas
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

2020-02-19 Thread Chet Ramey
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

2020-02-19 Thread Grisha Levit
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

2020-02-19 Thread Arfrever Frehtes Taifersar Arahesis
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

2020-02-19 Thread Arfrever Frehtes Taifersar Arahesis
${!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

2020-02-19 Thread Arfrever Frehtes Taifersar Arahesis
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

2020-02-19 Thread Chet Ramey
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

2020-02-19 Thread Arfrever Frehtes Taifersar Arahesis
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

2020-02-19 Thread Eli Schwartz
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

2020-02-19 Thread Arfrever Frehtes Taifersar Arahesis
> ${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

2020-02-19 Thread Arfrever Frehtes Taifersar Arahesis
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

2020-02-19 Thread Eli Schwartz
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

2020-02-19 Thread Harald van Dijk

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

2020-02-19 Thread Arfrever Frehtes Taifersar Arahesis
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

2020-02-19 Thread Robert Elz
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