Configuration Information [Automatically generated, do not change]: Machine: aarch64 OS: linux-gnu Compiler: gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='aarch64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='aarch64-unknown-linux-gnu' -DCONF_VENDOR='unknown' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -I. -I../. -I.././include -I.././lib -D_FORTIFY_SOURCE=2 -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -Wall uname output: Linux mcbin 4.9.0+ #249 SMP PREEMPT Sun Jan 1 17:28:33 GMT 2017 aarch64 aarch64 aarch64 GNU/Linux Machine Type: aarch64-unknown-linux-gnu
Bash Version: 4.3 Patch Level: 30 Release Status: release Description: Running: while :; do s=$(sleep .005 | cat); echo $s; done | uniq in a login shell on a virtual terminal or serial console results in the shell randomly logging out after ^C. Debugging reveals that: (a) the top-level shell sets the terminal PGRP and current process group to the shell's process ID (shell_pgrp as bash calls it). However, when bash gets around to reading input, it receives an EIO error - kernel debugging shows that this is because the TTY PGRP does not match the processes PGRP at this point. (b) the sub-shell running the "while" does not wait for the $(...) to finish before sending itself a SIGINT. (c) the sub-sub-shell for the $(...) waits for the "sleep" command to terminate, and then sets the PGRP and current process group to original_pgrp, which is the login process ID. stracing the shell (strace -tt -ff -o str.bash -p <shell-pid>) and grepping the resulting log files for SPGRP shows: str.bash.10928:17:38:38.745323 ioctl(255, TIOCGPGRP, [14119]) = 0 str.bash.10928:17:38:39.478119 ioctl(255, TIOCSPGRP, [10928]) = 0 str.bash.10928:17:38:39.480458 ioctl(255, TIOCSPGRP, [10928]) = 0 str.bash.10928:17:38:39.902027 ioctl(255, TIOCSPGRP, [10875]) = 0 str.bash.14119:17:38:38.719282 ioctl(255, TIOCSPGRP, [14119]) = 0 str.bash.14119:17:38:39.476968 ioctl(255, TIOCSPGRP, [10875]) = 0 str.bash.14120:17:38:38.718508 ioctl(255, TIOCSPGRP, [14119]) = 0 str.bash.14241:17:38:39.485459 ioctl(255, TIOCSPGRP, [10875]) = 0 str.bash.14243:17:38:39.477927 ioctl(255, TIOCSPGRP, [10875]) = 0 and stracing the login shell for terminal IO: str.bash.10928:17:38:39.482909 write(2, "root@mcbin:~# ", 14) = 14 str.bash.10928:17:38:39.483027 read(0, "\33", 1) = 1 str.bash.10928:17:38:39.870424 read(0, 0x7fc81f8737, 1) = -1 EIO (Input/output error) str.bash.10928:17:38:39.884115 write(2, "\7", 1) = 1 str.bash.10928:17:38:39.884212 read(0, 0x7fc81f87a7, 1) = -1 EIO (Input/output error) str.bash.10928:17:38:39.899960 write(2, "logout\n", 7) = 7 From the timestamps, you can see that PID 14241 changed the TTY PGRP between the write-out of the prompt, reading the first character of input, and attempting to read the subsequent characters - resulting in the shell logging itself out. Here, pid 10875 was the login process. Adding debug into give_terminal_to() changes the timing enough that it becomes very difficult to trigger. Remove the debug and it seems to be soo easy that bash is painful to use on such a terminal. (My command which discovered this was slightly more complex and useful than the above, but the above is a simpler test case which reproduces the problem.) Repeat-By: Login on a serial console. Probably logging in on a Linux virtual terminal will also be good enough. Not a SSH connection, there needs to be a login(8) process as bash's parent. Run: while :; do s=$(sleep .005 | cat); echo $s; done | uniq Hit ^c. Repeat a few times. Tested on a quad-core ARM64 machine and a dual-core 32-bit ARM machine.