[Toybox] Would someone please explain what bash is doing here?

Chet Ramey chet.ramey at case.edu
Sat May 23 15:51:27 PDT 2020


On 5/23/20 1:11 PM, Rob Landley wrote:
> Starting to open the job control can of worms, and:
> 
>   $ while true; do readlink /proc/self | cat - $$; done
>   24658
>   cat: 20032: No such file or directory
>   24660
>   cat: 20032: No such file or directory
>   24662
> 
> Is calling readlink and cat each time through the loop (true is a builtin), so
> the pid advances by 2 and the pipeline is NOT a subshell. 

Correct. Each element of a pipeline is executed in a subshell.


> But:
> 
>   $ echo hello | read i; echo $i
> 
> The read isn't saved because it's happening in a subshell context (so it sets an
> i that is discarded)?

Correct. Since the read is executed in a subshell, it can't affect its
parent's environment.

> 
> And then:
> 
>   $ while true; do continue | readlink /proc/self; done
>   28555
>   28557
>   28559
>   28561
> 
> Is advancing the pid by 2 each time, because the _continue_ is in its own process?

Each element of a pipeline is run in a subshell. That's how you can set its
process group and get it to respond to job control signals sent to the
terminal's process group. POSIX says you can run any element of a pipeline
in the current shell context, but in practice nobody does that for any one
but the last, and bash only does it if `lastpipe' is set.

It's truly a huge PITA to run the last element of the pipeline in the
current shell context when job control is enabled, keeping track of
process groups, handling signals like SIGTSTP, and forking at the right
time so you can suspend yourself if you need to. I've never been tempted.
I don't know how much trouble it was for Korn, but the zsh guys literally
fought bugs in that code for years.

> 
>   $ while true; do continue | cat; echo hello; done
>   hello
>   hello
>   hello
> 
>   $ while true; do break | cat; echo hello; done
>   hello
>   hello
>   hello
> 
> continue and break are silently NOP in a pipe?

What are they supposed to do? They can't affect the parent. All they can
do is complain, which would be annoying.

> 
> Also, just confirming: $$ only shows the PID of the top level bash process, and
> there's no variable that shows the PID of (subshells) even though the point of a
> subshell is to spawn a new process?

There is $BASHPID.


> P.S. this is old, but:
> 
>   $ for i in a b c & do echo $i; done
>   bash: syntax error near unexpected token `&'
> 
> But break & is fine? What does that even _mean_?

Come on. You at least have to implement the difference between a
`wordlist', which is a list of shell WORDs, and a command list, which
is terminated by the *operator* `&'.

Unquoted `&' is always an operator, it is never a WORD, and so it can't
appear in a list of WORDs, which is what follows `in'.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
		 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    chet at case.edu    http://tiswww.cwru.edu/~chet/



More information about the Toybox mailing list