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

Chet Ramey chet.ramey at case.edu
Wed May 27 12:31:48 PDT 2020


On 5/27/20 2:07 PM, Rob Landley wrote:

> Ok, I was trying to figure out what "jobs" should display when the pipeline it
> stopped is held together by && and || rather than just by | and... apparently
> you need parentheses or curly brackets to get it to do that, because suspended
> commands exit 'false' immediately and the rest of the line continues?

Yes, that's how everyone does it. Suspending the foreground job sets $?
to a non-zero value, and the next command in the AND-OR list executes
accordingly. There was a ferocious argument on the POSIX mailing list about
what a disgrace that is, but everyone still does it that way.

The problem is the granularity. The base object of job control is the
process group (pipeline), not a shell compound command.

> 
>   $ { echo hello; sleep 3; echo there; } | cat
>   hello
>   ^Z
>   [1]+  Stopped                 { echo hello; sleep 3; echo there; } | cat
>   $ fg
>   { echo hello; sleep 3; echo there; } | cat
>   there
> 
> Right. So it CAN include more stuff, it just doesn't. And instead the stuff
> RESUMES. (Is that posix what posix says to do? Does a shell script differ from
> interactive behavior here?)

Yes, that's how you have to handle it. And it doesn't depend on whether or
not the shell is interactive, in the sense that you can do some job control
stuff when the `-m' option is set.

But what are you going to do with a shell script when you suspend a
pipeline in it? Keep on going with reading commands in the script? That's
rarely going to be what the user wants. Most people expect the shell
running the script to get suspended when you hit it with SIGTSTP.

> 
> Ok, I guess pipeline has the tty (doo dah, doo dah) so signals go to it, but...
> 
>   $ sleep 10 || echo potato
>   ^C
>   landley at driftwood:~/toybox/toybox$ sleep 10 | cat || echo potato
>   ^C
> 
> That kills the later commands too? The interrupted command didn't just exit, it
> killed pending commands after it.

Yes, interrupting a command in a list cancels the execution of the entire
list. Bash didn't used to do that, but I got complaints and changed it.

> 
>   $ sleep 10 || echo hello
>   ^Z
>   [1]+  Stopped                 sleep 10
>   hello
> 
> Ok, it's not a pipeline thing, individual commands do it too. 

Technically, that's a pipeline. It's a child process whose process group is
set to the tty pgrp.


> Right. Am I gonna have to go read posix again? I dowanna read posix again.

POSIX doesn't say anything about the former (unless you want to go read the
discussion around bug 1254). The latter is ambiguous; the current bash
behavior is what users want and expect.

> 
> (And THIS is why I've held off on implementing job control because I have no
> current idea how to REGRESSION TEST this mess. 

It's hard. You can test the separate process group aspects of job control,
and you can hit things with SIGTSTP and SIGSTOP from other processes and
test fg/bg/jobs, but it's hard to simulate keyboard signals.


> The man page says "delayed suspend character" (CTRL-Y) is a thing, but as far as
> I can tell it isn't. This was some GNU Hurd feature maybe?

No, it's really part of the tty driver going all the way back to 4.1 BSD.
Readline turns it off because it uses ^Y for other things. Plus it's
rarely useful.

> 
> The man page has more "written by somebody who already knows it" stuff:
> 
>        referred to as %n.  A job may also be referred to using a prefix of the
>        name used to start it, or using a substring that appears in its command
>        line.  For example, %ce refers to  a  stopped  ce  job.   If  a  prefix
>        matches  more  than one job, bash reports an error.  Using %?ce, on the
>        other hand, refers to any job containing the string ce in  its  command
>        line.   If  the  substring  matches  more than one job, bash reports an
> 
> That "%?ce" is a specific example, not an explanation of what's happening here.

It's a specific example of a program named `ce' being suspended. It could
be any program. That's why the man page has `ce' in bold.

Since the first sentence in that section says that `%' starts a job spec,
it's difficult to see how `%ce' doesn't refer to `the name used to start
it'.


> Is it because "?" is a wildcard, or because %? is a special prefix? 

It's because `%' introduces the job spec, and `?' is the notation to refer
to the substring of the job name, so the latter.

> That
> question mark isn't going to act as a wildcard and match a filesystem character
> during normal wildcard processing, right?

It could. These are invariably used as arguments to builtins, and undergo
all the usual word expansions.


> If there's a %xce in the current
> directory, it won't resolve to that? 

It could. Such filenames are extremely rare. I've never actually had a bug
report complaining about this.

> The % is parsed _before_ wildcards and
> suppresses normal wildcard expansion? 

No. fg/bg/jobs/kill/wait/disown are not special in that regard.

> If a $variable expands to %?ce does it
> still count? 

Yes, when it's used as an argument to a shell builtin.

> How does this interact with quoting? Is kill "%?ce" different from
> kill %?ce or are they the same?

As long as `kill' sees the job spec, it treats it the same.

> 
> Ordinarily I would start assembling a list of regression tests to add to sh.test
> to determine/demonstrate the behavior I need to implement, but... backgrounding!

It's not easy. `bg' is not that hard once you have a job id. But getting
a job to stop by hitting it with a signal from a separate process is the
hard part.

> Asynchronous! Not really designed to be scripted!

Asynchronous jobs are easy. Once you have something in the background, and
you know its job number or how to refer to it using %name, you can run bg
and fg to your heart's content, use `kill' to kill it, and use `wait' to
clean up.

Job control, at least the terminal-based aspects of it, is not really
designed for use by non-interactive shells.  That's just the reality of it.

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