command substitution when timing grouped commands fails

2023-09-07 Thread hackerb9
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS: -g -O2 -fstack-protector-strong -Wformat 
-Werror=format-security -Wall
uname output: Linux abyssal 6.4.0-3-amd64 #1 SMP PREEMPT_DYNAMIC Debian 
6.4.11-1 (2023-08-17) x86_64 GNU/Linux
Machine Type: x86_64-pc-linux-gnu

Bash Version: 5.2
Patch Level: 15
Release Status: release

Description:

Bash gives a syntax error when using the $(...) form of
command substitution and timing grouped commands.

However, Bash works correctly when using the `...` form of
command substitution.


Repeat-By:

The 'time' built-in command can measure a group of commands
run in a subshell, for example:

$ time (date; sleep 1)
Thu Sep  7 05:19:21 AM PDT 2023

real0m1.005s
user0m0.003s
sys 0m0.001s

Attempting to save the output of time to a variable fails when
using $(...) command substitution. For example,

$ x=$( time ( date; sleep 1 ) 2>&1 )
-bash: syntax error near unexpected token `date'

However, old versions of bash (~2016) used to work correctly.
And, indeed, even the current version of bash works if one
uses backticks for command substitution.

$ x=` time ( date; sleep 1 ) 2>&1 `
$   # no error

There should be no difference between $(...) and `...`.




bash signal during wait + read causes unkillable 100% CPU usage

2018-09-17 Thread hackerb9
Configuration Information [Automatically generated, do not change]:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i686' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i686-pc-linux-gnu' 
-DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I../. -I.././include -I.././lib  -Wdate-time 
-D_FORTIFY_SOURCE=2 -g -O2 -fdebug-prefix-map=/build/bash-u3hlEB/bash-4.4.18=. 
-fstack-protector-strong -Wformat -Werror=format-security -Wall 
-Wno-parentheses -Wno-format-security
uname output: Linux thomas 4.18.0-7-generic #8-Ubuntu SMP Tue Aug 28 18:22:50 
UTC 2018 i686 i686 i686 GNU/Linux
Machine Type: i686-pc-linux-gnu

Bash Version: 4.4
Patch Level: 19
Release Status: release

Description:

I was trying to work around the problem of bash not being able to
cancel the read builtin command when a signal comes in and I stumbled
upon this (perhaps unrelated) bug. I'm not sure exactly what's going
on but I have a simple script that demonstrates the problem.

Repeat-By:

Run the following script. Quickly hit a key, then wait to be prompted
to hit Control C. When you hit Control C, the process should stop
responding and your CPU usage should go to 100%. The HUP, TERM and
QUIT signals are ignored.

- 8< - 8< - 8< - CUT HERE - 8< - 8< - 8< - 
#!/bin/bash

trap cleanup EXIT
cleanup() {
echo "Huh. There was supposed to be an earth-shattering kaboom."
echo "The bug wasn't triggered. Did you hit the first key quickly?"
echo "Or, perhaps Bash $BASH_VERSION isn't buggy?"
echo "This test was designed for Bash 4.4.19(1) on Ubuntu Cosmic 
Cuttlefish."
}

trap huphandler SIGHUP
huphandler() {
# This handler doesn't actually do anything.
# The important thing is that HUP interrupts the wait.
return
}

# Send a SIGHUP to ourselves to interrupt the wait and start "read".
(sleep 2;  kill -1 $$; sleep 2; echo -e "\nB: Now try ^C and see what breaks.") 
&

echo "A: Quickly press a key before part B! "
while true; do
wait
read -p "Kaboom? " -n1
echo 
done
- 8< - 8< - 8< - CUT HERE - 8< - 8< - 8< - 


I tried attaching to the process with GDB. The backtrace showed it
being in jobs.c:wait_sigint_handler() or zread.c:zread(). This may be
a red herring, but there is a comment in zread.c with an XXX and a
question that may be worth investigating:

60check_signals_and_traps ();   /* XXX - should it be 
check_signals()? */

Here is a more extensive log of what gdb said:

$ gdb -p 27088
Attaching to process 27088
Reading symbols from /src/bash-4.4.18/bash...done.
Reading symbols from /lib/i386-linux-gnu/libtinfo.so.6...(no debugging symbols 
found)...done.
Reading symbols from /lib/i386-linux-gnu/libdl.so.2...Reading symbols from 
/usr/lib/debug//lib/i386-linux-gnu/libdl-2.28.so...done.
done.
Reading symbols from /lib/i386-linux-gnu/libc.so.6...Reading symbols from 
/usr/lib/debug//lib/i386-linux-gnu/libc-2.28.so...done.
done.
Reading symbols from /lib/ld-linux.so.2...Reading symbols from 
/usr/lib/debug//lib/i386-linux-gnu/ld-2.28.so...done.
done.

wait_sigint_handler (sig=2) at jobs.c:2476
2476  if (interrupt_immediately ||

(gdb) list
2471wait_sigint_handler (sig)
2472 int sig;
2473{
2474  SigHandler *sigint_handler;
2475
2476  if (interrupt_immediately ||
2477  (this_shell_builtin && this_shell_builtin == wait_builtin))
2478{
2479  last_command_exit_value = 128+SIGINT;
2480  restore_sigint_handler ();
2481  /* If we got a SIGINT while in `wait', and SIGINT is trapped, do
2482 what POSIX.2 says (see builtins/wait.def for more info). */
2483  if (this_shell_builtin && this_shell_builtin == wait_builtin &&
2484  signal_is_trapped (SIGINT) &&
2485  ((sigint_handler = trap_to_sighandler (SIGINT)) == 
trap_handler))
2486{
2487  trap_handler (SIGINT);/* set pending_traps[SIGINT] */
2488  wait_signal_received = SIGINT;
2489  if (interrupt_immediately && wait_intr_flag)
2490{
(gdb) bt
#0  wait_sigint_handler (sig=2) at jobs.c:2476
#1  
#2  0xb7f09d41 in __kernel_vsyscall ()
#3  0xb7dbc5a7 in __GI___libc_read (fd=0, buf=0xbf956a56, nbytes=1)
at ../sysdeps/unix/sysv/linux/read.c:26
#4  0x0052dce1 in read (__nbytes=1, __buf=0xbf956a56, __fd=0)
at /usr/include/i386-linux-gnu/bits/unistd.h:44
#5  zread (fd=0, buf=0xbf956a56 "V", len=1) at zread.c:56
#6  0x00519c23 in read_builtin (list=0x0) at ./read.def:585
#7  0x004bacc0 in execute_builtin (
builtin=builtin@entry=0x519360 , flags=flags@entry=0, 
subshell=0, words=) at execute_cmd.c:4535
#8  0x004bd75a in execute_builtin_or_function (flags=, 
fds_to_close=, redirects=, var=0x0, 
builtin=0x519360 , words=0x13367c8) at execute_cmd.c:5028
#9  execute_simple_command (simple_command=, 
pipe_in=,