I started writing up the changes for bug 1254 but got stuck when I
looked at the uses of "command" in the description of wait. It says
that when you wait for a job control ID, "The exit status of wait shall be
determined by the last command in the pipeline". To understand why it
used "the pipeline" here, I looked at the definition of "Job" in XBD, and
saw that it does indeed relate a job to a (single) pipeline.  This is, of
course, wrong - a job is an AND-OR list, not a pipeline:

$ sleep 3 && sleep 4 &
[1]     3627
$ jobs
[1] +  Running                 sleep 3 && sleep 4 &

At least, it is for a background job (because a child shell is forked
to run the AND-OR list and it is that child which is the process group
leader).  For foreground jobs, shells differ:

Ksh93 has it as an AND-OR list:

$ sleep 3 && sleep 4        
^Z[1] + Stopped                  sleep 3 && sleep 4
$ jobs
[1] + Stopped                  sleep 3 && sleep 4

Bash does not:

$ sleep 3 && sleep 4
^Z
[1]+  Stopped                 sleep 3
$ jobs
[1]+  Stopped                 sleep 3

While the ksh93 behaviour might seem more consistent with background
jobs, the bash behaviour may actually make more sense if you think of
a job as being a set of processes that have the same process group ID.
And, indeed, the current definition of "Job" talks about processes all
being in the same process group.  In ksh93 this is true for a background
job (as expected, for the reason I gave above), but is not true for a
foreground job:

$ ps -o pid,pgid,comm && ps -o pid,pgid,comm &
[1]     3710
$   PID  PGID COMMAND
 3646  3646 ksh
 3710  3710 ksh
 3711  3710 ps
  PID  PGID COMMAND
 3646  3646 ksh
 3710  3710 ps
$ ps -o pid,pgid,comm && ps -o pid,pgid,comm  
  PID  PGID COMMAND
 3646  3646 ksh
 3714  3714 ps
  PID  PGID COMMAND
 3646  3646 ksh
 3715  3715 ps

In the background case, a child shell was created to run the asynchronous
AND-OR list and was made process group leader (3710), and the ps commands
both had this as their process group.  In the foreground case, each ps
command was placed in its own process group (3714 and 3715).

Then there is the complication of shells being allowed to execute some
of the commands in a pipeline in the current shell environment.  To
match the current definition of "Job", the shell would have to change
its own process group ID to match the process group ID of the other
commands in the pipeline.  It appears that ksh93 doesn't do that:

$ (sleep 2; ps -o pid,pgid,comm) | { read l1; read l2; read l3; read l4; }; 
printf '%s\n' "$l1" "$l2" "$l3" "$l4"   
PID  PGID COMMAND
3646  3646 ksh
3808  3808 ps

$ 

and I suspect that if it did, it would interfere with the shell's role as
session leader.  This has implications for how the shell handles foreground
jobs that are stopped by a signal.

It looks like we are going to have to revisit all of the wording relating
to job control in the shell. As a first step we should agree on a new
definition of "Job".  Here is an attempt which tries to deal with the
issues I raised above, but I'm not sure it is appropriate to include all
of it in a definition - it might be better to move part of it elsewhere.

On page 65 line 1924 section 3.202 Job, change:

    A set of processes, comprising a shell pipeline, and any processes
    descended from it, that are all in the same process group.

    <b>Note:</b> See also [xref to XCU 2.9.2 Pipelines].

to:

    An AND-OR list or a pipeline executed from the current shell environment
    when job control is enabled in that environment.  An asynchronous AND-OR
    list shall form a single <i>background job</i> and the child process
    created to execute the AND-OR list shall be made a process group leader
    so that the executed commands inherit its process group ID. For a
    sequential AND-OR list, either:

    * The whole AND-OR list shall form a single <i>foreground job</i>, or

    * Each pipeline in the AND-OR list shall form a separate <i>foreground
      job</i>.

    For each pipeline in a foreground job, if the pipeline is executed,
    the set of processes comprising the pipeline, and any processes
    descended from it, shall all be in the same process group, unless
    the shell executes some of the commands in the pipeline in the
    current shell environment and others in a subshell environment; in
    this case the process group ID of the current shell shall not
    change and the process group ID that the other processes all share
    shall differ from the process group ID of the current shell (which
    means that a SIGSTOP, SIGTSTP, SIGTTIN, or SIGTTOU signal sent to
    one of those process groups does not cause the whole pipeline to
    stop).

    <b>Note:</b> See also [xref to XCU 2.9.3 Lists] and [xref to XCU
    2.12 Shell Execution Environment].

The issue of stop signals seems particularly thorny, and it appears that
ksh93 does not handle it well.  In experiments, it is easy to come up
with scenarios where the shell becomes unresponsive after typing Ctrl-Z
and the only way to bring it back to life is to run "kill -s CONT" in
another terminal.  For example:

sleep 10 | read x

Hitting Ctrl-Z while this is running results in the shell being stopped
and Ctrl-C does not do anything.  Since sleep is built-in to ksh93 I
also tried:

/bin/sleep 10 | read x

where Ctrl-Z resulted in the sleep being stopped, but even though the 
shell was not stopped, Ctrl-C still had no effect (presumably because
the resulting SIGINT was only sent to the sleep).

I think in both of these cases the shell ought to notice what is happening
(by catching SIGTSTP in the first case, and seeing via SIGCHLD that sleep
was stopped with SIGTSTP in the second case) and mimic the "normal"
job control behaviour.  However, I'm not sure if we should require this
or should just treat it as a quality-of-implementation issue.

-- 
Geoff Clare <[email protected]>
The Open Group, Apex Plaza, Forbury Road, Reading, RG1 1AX, England

Reply via email to