mainThe GNU Bourne-Again SHell - Support: sr #111030, Concurrent 'script's run from...

 
 

sr #111030: Concurrent 'script's run from inside process substitution can mess with terminal output

Submitter:  Zack Porter <zaporter>
Submitted:  Sun 03 Mar 2024 02:33:34 AM UTC
   
 
Category:  None Priority:  5 - Normal
Severity:  3 - Normal Status:  Done
Privacy:  Public Assigned to:  None
Open/Closed:  Open Operating System:  GNU/Linux
* Mandatory Fields

Add a New Comment Rich Markup
   

Tue 05 Mar 2024 05:58:55 PM UTC, comment #3: 

Ah, that makes sense. I hadn't considered that script was sharing the same terminal as the main process group and was editing terminal serial port settings. After reading a bit more about canonical mode, this makes more sense.

You're correct that redirecting stdin from /dev/null fixed the issue.

I'll submit an issue to util-linux and see if they're interested in mentioning this in the NOTES or BUGS section of script's man page (I would've expected to see some mention of this in there).

Thank you for your time! I deeply appreciate it.

Zack Porter <zaporter>
Tue 05 Mar 2024 04:13:49 PM UTC, comment #2: 

You can inhibit the TCGETS/TCSETS by redirecting script's input from /dev/null.

I changed process substitution to use /dev/null as stdin, like any other asynchronous process without job control, in bash-5.1-beta. I explained the rationale in

https://lists.gnu.org/archive/html/bug-bash/2020-09/msg00024.html

but had to change it back as the result of

https://lists.gnu.org/archive/html/bug-bash/2020-09/msg00021.html

So you still have to do that part yourself.

Chet Ramey <chet>
Group administrator
Tue 05 Mar 2024 03:44:30 PM UTC, comment #1: 

Much of this can be explained by the fact that script, running asynchronously, changes the terminal settings to disable icanon mode. Depending on how the processes get scheduled, the terminal modes will be in an indeterminate state for subsequent invocations of script. Any writes to the terminal are going to be affected by the changed terminal modes, such as ocrnl and onlcr.

If one of the script invocations happens to leave the terminal in -icanon mode, but exits successfully, bash will leave the terminal settings as they are. (Otherwise, stty could never work.) This is one difference between bash and zsh.

Since the process substitution jobs share the same controlling terminal and are in the foreground process group, they are allowed to retrieve and set the terminal modes, and do.

Aside from the first process substitution, and possibly part of the second, the reads and writes consume the entire output of the process substitution, since the data all fits into a pipe. So it's not a case of writes being interrupted, though a child exiting due to a process substitution completing could interrupt one of the system calls the shell performs.

All the data gets written, but to a terminal that may be in a non-canonical state. Strangely, one of the process substitutions generates more data than the others (writing 5536 bytes instead of 5485).

I used strace to look at all this.

Chet Ramey <chet>
Group administrator
Sun 03 Mar 2024 02:33:34 AM UTC, original submission:  

Description


I suspect that there is a bug in bash 5.2 (p14 & p26) that causes two different invocations of `script` within process substitution to collide. Ex: `cat <(something that runs script) <(something else that runs script)`. This can lead to extra indentations & whitespace during and after their execution (until the end of the terminal session)

I ran into this issue when trying to run some linters in parallel but print their output sequentially (using script to keep color output (sigh))

Reproduction


test.sh:

#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail
if [[ "${TRACE-0}" == "1" ]]; then
    set -o xtrace
fi

function run() {
    script -eqfB /dev/null -c "./count.sh"
}
cat <(run)
echo "all is good"
cat <(run) <(run) <(run) <(run) <(run) <(run) <(run) <(run) <(run)
echo "all is sometimes not good"


count.sh

#!/usr/bin/env bash

PREFIX="I love bash. I love bash. I love bash."
echo "hi"
for i in $(seq 1 50);
do
    sleep 0.01
    echo -en "$PREFIX$i"
    echo -e "\e[2K\e[1G\e[1A\e[2K\e[1G\e[90\e[36m$PREFIX$i"
done


Expected output (happens on my computer 1/8 tries or so (Changing the sleep time in count.sh or the number of <(run)'s can drastically change reproducibility)):

➜  ~ ./test.sh
I love bash. I love bash. I love bash.50
all is good
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
all is sometimes not good


Actual Output:

➜  ~ ./test.sh
I love bash. I love bash. I love bash.50
all is good
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
I love bash. I love bash. I love bash.50
                                        all is sometimes not good
                                                                 %
                        ➜  ~ #now my prompt is out here and terminal output is indented for the rest of the session


Environment Info


➜  ~ bash --version
GNU bash, version 5.2.26(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.


NixOS

Other important info

- Swapping to zsh from bash (just in test.sh) causes the bug to no longer repro
- Reproduces in both alacritty and xterm
- Does not reproduce if I don't run "count.sh" from script

Zack Porter <zaporter>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by chet (Posted a comment)
  • -email is unavailable- added by zaporter (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 2 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2024-03-05 chet StatusNeed Info Done
    2024-03-05 chet StatusNone Need Info

    Back to the top

    Powered by Savane 3.13-02a9.
    Corresponding source code