[mod.std.unix] mod.std.unix P1003 job control proposal

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (10/12/86)

From: im4u!caip!hplabs!hpda!hpisoa1!davel@sally.utexas.edu (Dave Lennert)
Date: Thu, 9 Oct 86 14:06:30 pdt

Attached is the P1003 job control proposal.  The first file contains 
the text as accepted at the September P1003 meeting in Palo Alto.
Note that this text sometimes replaces, and sometimes augments,
existing POSIX text.  The second file contains the problems noticed 
since then and the proposed resolutions.

    Dave Lennert                ucbvax!hpda!davel               [UUCP]
    Hewlett-Packard - 47UX      ihnp4!hplabs!hpda!davel         [UUCP]
    19447 Pruneridge Ave.       hpda!davel@ucb-vax.ARPA         [ARPA]
    Cupertino, CA  95014        (408) 447-6325                  [AT&T]


# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by davel at hpisoa1 on Thu Oct  9 13:23:24 1986
#
# This archive contains:
#	acceptedtext	problems	
#

echo x - acceptedtext
cat >acceptedtext <<'@EOF'
							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       2.3  General Terms
       Replace or add the following definitions:


       job control option
	     Job control allows	users to selectively stop (suspend)
	     the execution of processes	and continue (resume) their
	     execution at a later point.  The user typically
	     employs this facility via the interactive interface
	     jointly supplied by the terminal I/O driver and a
	     command interpreter.  Conforming implementations may
	     optionally	support	job control facilities (see
	     Symbolic Constants	  2.10).  Portions of the standard
	     operating system interface	which are required only	on
	     implementations which support the job control option
	     are so labelled.


       process group leader
	     A process group leader is a process whose process ID
	     is	the same as its	process	group ID.  Any process that
	     is	not a process group leader may detach itself from
	     its process group and becomes the process group leader
	     of	a new process group by calling either the setpgrp()
	     or	setpgrp2() function, which can cause a process to
	     become either a session process group leader or a job
	     process group leader, respectively.  Job process group
	     leaders can exist on implementations which	support	the
	     job control option.


       saved process group ID
	     An	active process has a saved process group ID that is
	     set to the	saved process group ID of the parent
	     process at	the time of creation of	the process (via
	     the fork()	function).  It is reset	to the process
	     group ID of the process when the process successfully
	     calls one of the exec functions.


       2.10  Symbolic Constants
       Add the following new constant after the	IEEE1003 constant
       defintion:


       IEEE1003job
	     If	this symbol is defined then the	implementation
	     supports the job control option.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       3.2.1  Wait for Process Termination
       Functions: wait(), wait2()

       3.2.1.1	Synopsis
       Add the following at the	end of the section:

		 #include <sys/wait.h>
		 int wait2 (stat_loc, options)
		 int *stat_loc;
		 int options;

       3.2.1.2	Description
       Add the following at the	end of the section:

       If the wait2() variant is used, then there are two options
       available for modifying the behavior of the system call.
       They may	be combined by oring them together.  The first is
       WNOHANG which prevents wait2() from suspending the calling
       process even if there are children to wait for.	In this
       case, a value of	zero is	returned indicating there are no
       children	which have stopped or died.  If	the second option
       WUNTRACED is set, wait2() will also return information when
       children	of the current process are stopped because they
       received	a SIGTTIN, SIGTTOU, SIGTSTP, or	SIGSTOP	signal.

       The wait2() function is provided	if the implementation
       supports	the job	control	option.

       3.2.1.3	Returns
       Add the following at the	end of the section:

       If wait2() is called, the WNOHANG option	is used, and there
       are no stopped or terminated children, then a value of zero
       is returned.  Otherwise,	a value	of -1 is returned and errno
       shall be	set to indicate	the error.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       In section 3.2.2.2 Description of the _exit function replace
       the paragraph:

	     If	the process is a process group leader, the SIGHUP
	     signal may	be sent	to each	process	that has a process
	     group ID equal to that of the calling process.

       with:

	     If	the process is a session process group leader, the
	     SIGHUP signal may be sent to each process that has	a
	     process group ID equal to that of the calling process;
	     also, all such processes may have their process group
	     ID	set to zero.

	     If	the implementation supports the	job control option
	     and if the	calling	process	has child processes that
	     are stopped, they will be sent SIGHUP and SIGCONT
	     signals.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       3.3.1  Signal Names

       3.3.1.2	Description
       Add the following at the	end of the signals list.

       SIGCLD	+   child process terminated

       If the implementation supports the job control option then
       the following are defined:

       SIGSTOP	 #    stop (cannot be caught or	ignored)
       SIGTSTP	 #    stop signal generated from keyboard
       SIGTTIN	 #    background read attempted	from control terminal
       SIGTTOU	 #    background write attempted to control terminal
       SIGCONT	 %+   continue after stop

	  +  Indicates that the	action on SIG_DFL is to	ignore the
	     signal, rather than terminate the process.

	  #  Indicates that the	action on SIG_DFL is to	stop rather
	     than terminate the	process.

	  %  Indicates that the	signal will not	be held	off by a
	     stopped process.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       In section 3.3.2.2 Description of the kill() function, add
       the following paragraph at the end of the Description
       section.

       As a single special case	on implementations that	support	the
       job control option, the continue	signal SIGCONT can be sent
       to any process that is a	descendant of the current process.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       3.3.3  Signal Processing

       3.3.3.2	Description
       Replace the SIG_DFL and SIG_IGN discussions with	the
       following text.	(Note that this	text needs rewording based
       on the signal working group decisions from Palo Alto, 9/86.
       Bob Lenk	is planning on merging this text with the proposal
       he sends	you.  So you should only have to verify	that he	has
       done this.)

       SIG_DFL - signal	specific default action
	     For all signals listed in the table in <signal.h>
	     3.3.1, unless otherwise indicated the default action
	     is	either simple abnormal termination or abnormal
	     termination with actions of the receiving process.
	     The result	of abnormal termination	with actions is
	     implementation-dependent.	Abnormal termination with
	     actions may result	in the creation	of a file named
	     core in the receiving process's current directory.
	     Such a core file should contain sufficient	information
	     to	document the state of the process at the time of
	     the signal.

	     For certain indicated signals listed in the table in
	     <signal.h>	  3.3.1, the default action is to stop
	     (suspend) the receiving process.  While a process is
	     stopped, any additional signals that are sent to the
	     process will be held off until the	process	is
	     continued.	 An exception to this is SIGCONT which
	     always causes the receiving process to continue if	it
	     is	stopped.  When a process is continued, pending
	     signals will be processed.

	     For certain indicated signals listed in the table in
	     <signal.h>	  3.3.1, the default action is to ignore
	     the signal.

	     Signals not described <signal.h>	3.3.1 may have
	     other default actions.

       SIG_IGN - ignore	signal
	     The signal	sig is to be ignored.  The signals SIGKILL
	     and SIGSTOP shall not be ignored.	Ignoring SIGCLD	may
	     cause terminating children	to be ignored by the wait
	     functions	 3.2.1.

       At the end of the "function address - catch signal"
       discussion, replace the statement:

       The signal SIGKILL cannot be caught.

       with:

       The signals SIGKILL and SIGSTOP cannot be caught.

       3.3.3.4	Errors
       Replace:

       [EINVAL]	The value sig is either	an illegal signal number or
	     SIGKILL.

       with:

       [EINVAL]	The value sig is either	an illegal signal number,
	     or	is equal to SIGKILL or SIGSTOP.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       Replace all of section 4.3.1 with:



       4.3.1  Get Process Group	ID
       Functions: getpgrp(), getpgrp2()

       4.3.1.1	Synopsis

		 int getpgrp ( )

		 int getpgrp2 (pid)
		 int pid;

       4.3.1.2	Description
       The getpgrp() function returns the process group	ID of the
       calling process.

       The getpgrp2() function returns the process group ID of the
       specified process.  If pid is zero, the call applies to the
       current process.	 For this to be	allowed, the real or
       effective user ID of the	current	process	must match the real
       or effective user ID of the referenced process, the
       effective user ID of the	current	process	must be	super-user,
       or the referenced process must be a descendant of the
       current process.	 The saved set-user ID of the referenced
       process may be checked in place of its effective	user ID.

       The getpgrp2() function is provided if the implementation
       supports	the job	control	option.

       4.3.1.3	Returns
       The getpgrp() function returns the process group	ID of the
       calling process.

       Upon successful completion, the getpgrp2() function returns
       the process group ID of the specified process.  Otherwise a
       value of	-1 is returned and errno is set	to indicate the
       error.

       4.3.1.4	Errors
       If the getpgrp2() function returns -1, the value	stored in
       errno may be interpreted	as follows:

       [EPERM]	   The effective user ID of the	current	process	is
		   not super-user, the real or effective user ID of
		   the current process does not	match the real or
		   effective user ID (or saved set-user	ID) of the
		   specified process, and the specified	process	is
		   not a descendant of the current process.

       [ESRCH]	   No process can be found corresponding to that
		   specified by	pid.

       4.3.1.5	References
       setpgrp()   4.3.2, signal()   3.3.3.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       Replace all of section 4.3.2 with:



       4.3.2  Set Process Group
       Functions: setpgrp(), setpgrp2()

       4.3.2.1	Synopsis

		 int setpgrp ( )

		 int setpgrp2 (pid, pgrp)
		 int pid, pgrp;

       4.3.2.2	Description
       The setpgrp() function sets the process group ID	of the
       calling process to the process ID of the	calling	process	and
       returns the new process group ID.  The calling process
       becomes a session process group leader.

       The setpgrp() function relinquishes the process's
       controlling terminal unless the process is already the
       process group leader.

       The setpgrp2() function sets the	process	group ID of the
       process specified by pid	to be pgrp.  If	pid is zero, the
       process group ID	of the calling process will be affected.
       If the affected process's new process group ID is the same
       as its process ID then the affected process becomes a job
       control process group leader.

       The setpgrp2() function does not	affect the process's
       controlling terminal.

       The setpgrp2() function is provided if the implementation
       supports	the job	control	option.

       The following condition must be met for the setpgrp2()
       function	to succeed; otherwise, the error [EINVAL] is
       returned:

	    The	value of pgrp must be in the range of valid process
	    group ID values, or	it must	be zero	("no process
	    group").

       In addition, one	or more	of the following conditions must be
       met for the setpgrp2() function to succeed; otherwise, the
       error [EPERM] is	returned:

	    The	effective user ID of the calling process is super-
	    user.

	    The	affected process is a descendant of the	calling
	    process.

	    The	real or	effective user ID of the calling process
	    matches the	real or	effective user ID of the affected
	    process.  The saved	set-user ID of the affected process
	    may	be checked in place of its effective user ID.

       In addition, one	or more	of the following conditions must be
       met for the setpgrp2() function to succeed, otherwise, the
       error [EPERM] is	returned:

	    The	effective user ID of the calling process is super-
	    user.

	    The	value of pgrp matches the saved	process	group ID of
	    the	calling	process.

	    All	processes with a process ID or process group ID
	    that is the	same as	pgrp have the same real	or
	    effective user ID as the real or effective user ID of
	    the	calling	process, or are	descendants of the calling
	    process.  The saved	set-user ID of the related
	    processes may be checked in	place of their effective
	    user ID.

       4.3.2.3	Returns
       The setpgrp() function returns the value	of the new process
       group ID.

       Upon successful completion, the setpgrp2() function returns
       a value of 0.  Otherwise, a value of -1 is returned and
       errno is	set to indicate	the error.

       4.3.2.4	Errors
       If the setpgrp2() function returns -1, the value	stored in
       errno may be interpreted	as follows:

       [ESRCH]	   No process can be found corresponding to that
		   specified by	pid.

       [EPERM]	   The effective user ID of the	calling	process	is
		   not super-user; and the real	or effective user
		   ID of the calling process does not match the
		   real	or effective user ID (or saved set-user	ID)
		   of the specified process; and the specified
		   processes are not descendants of the	calling
		   process.

       [EPERM]	   The effective user ID of the	calling	process	is
		   not super-user; and the value pgrp does not
		   match the saved process group ID of calling
		   process; and	a process exists that is not a
		   descendant of the calling process and whose
		   process ID or process group ID match	pgrp, while
		   neither the real or effective user ID (or saved
		   set-user ID)	of this	process	match either the
		   real	or effective user ID of	the calling
		   process.

       [EINVAL]	   The value for pgrp is outside the range of valid
		   process group ID values and is non-zero.

       4.3.2.5	References
       exec   3.1.2, _exit()   3.2.2, fork()   3.1.1, getpid()
       4.1.1, kill()   3.3.2, signal()	 3.3.3.

----------------------------------------------------------------------

							       IEEE
       SYSTEM FOR COMPUTER ENVIRONMENTS			 Std 1003.1

       Alter the forthcoming reliable signals proposal,	the
       sigvector() description,	by adding the following	paragraph:

       The sv_flags field can be used to modify	the receipt the
       specified signal.  If sig is SIGCLD and the implementation
       supports	the job	control	option,	the following flag bit can
       be set in sv_flags:

	  SV_CLDSTOP   Also generate SIGCLD when children stop

@EOF

chmod 664 acceptedtext

echo x - problems
cat >problems <<'@EOF'
There are two omissions in the job control specification that
have come to light since it was accepted at the P1003 meeting
in Palo Alto.  There will be forthcoming proposals to correct
these.

Omission 1:

Bob Lenk noticed that, in adding SIGCLD to the required portion of
POSIX, we neglected to deal with the issue of what happens when
SIGCLD is set to SIG_IGN.  Specifically, on ATT this causes 
terminated children to be invisible to wait*() while on BSD there
is no such side effect.  Bob Lenk feels the best way to handle this
is to disallow conforming applications from setting SIGCLD to SIG_IGN.
(There is no advantage to using SIG_IGN over SIG_DFL in the case
of SIGCLD anyway.)  Bob is planning on submitting a cleanup proposal
proposing this.

Omission 2:

Doug Gwyn pointed out the following omission:

The changes to section 3.2.1.2 for wait2() did not contain a
description of the returned status information in the case
of stopped children.

I've submitted a proposal to add the following additional text:

[OLD TEXT FOR CONTEXT:]

wait2() will also return information when children of the
current process are stopped because they received a SIGTTIN,
SIGTTOU, SIGTSTP, or SIGSTOP signal.

[NEW TEXT:]

In this case, the status information can also be interpreted
in the following way:

    If the child process stopped, the 8 bits of status
    (corresponding to the octal value 0177400) will contain
    the number of the signal that caused the process to
    stop and the low order 8 bits corresponding to the
    octal value 0377 will be set equal to the octal value
    0177.
@EOF

chmod 664 problems

exit 0


Volume-Number: Volume 7, Number 53

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (10/12/86)

From: hplabs!hpda!hpisoa1!davel (Dave Lennert)
Date: Thu, 09 Oct 86 22:33:31 -0800

As an addendum to the P1003 job control proposal text I submitted,
here's a paper describing the 4.2 job control implementation, the
System V incompatibilities, and how they were resolved.  This was
the background investigation that went into the P1003 proposal.

This is the same paper that appears in the Atlanta USENIX proceedings.
[ June 1986, pp. 459-474.  -mod ]
It uses the -ms macro package.

    Dave Lennert                ucbvax!hpda!davel               [UUCP]
    Hewlett-Packard - 47UX      ihnp4!hplabs!hpda!davel         [UUCP]
    19447 Pruneridge Ave.       hpda!davel@ucb-vax.ARPA         [ARPA]
    Cupertino, CA  95014        (408) 447-6325                  [AT&T]


# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by davel on Thu Oct  9 22:29:34 PDT 1986
# Contents:  jobpaper.ms
 
echo x - jobpaper.ms
sed 's/^@//' > "jobpaper.ms" <<'@//E*O*F jobpaper.ms//'
@.de PB
@.sp 1
@.RS
@.nf
@..
@.de PE
@.fi
@.RE
@.sp 1
@..
@.DA
@.	\" Put page numbers at bottom center rather than top center
@.rm CH
@.ds CF - \\n(PN -
@.	\" UX - UNIX macro
@.de UX
@.ie \\n(UX \s-1UNIX\s0\\$1
@.el \{\
\s-1UNIX\s0\\$1\(dg
@.FS
\(dg \s-1UNIX\s0 is a trademark of AT&T.
@.FE
@.nr UX 1
@.\}
@..
@.TL
A System V Compatible Implementation of 4.2BSD Job Control
@.AU
David C. Lennert
@.AI
Hewlett-Packard Company
Information Technology Group
hplabs\^!\^hpda\^!\^davel
@.AB
This paper gives an overview of how process groups and controlling
terminals are handled in System V and 4.2BSD and then
discusses the effect 4.2BSD job control has on these things.
A modified 4.2BSD interface is discussed which supports 4.2BSD job control
functionality but in a way which allows AT&T System V compatibility.
This interface has been implemented in Hewlett-Packard's 
@.UX
system, HP-UX.
@.AE
@.sp 1
@.NH
INTRODUCTION
@.PP
The job control functionality first introduced into
@.UX
by Jim Kulp of IIASA and later provided by 4.2BSD
@.UX
has become a \fIde facto\fP industry standard.
However, this job control facility, as implemented in 4.2BSD, is incompatible
in several respects with System V.
@.PP
Recently a proposal was submitted to the IEEE P1003 Portable Operating
System standard committee by Sun Microsystems [Harris86] which attempts
to define
4.2BSD job control functionality in a way compatible with System V.
Hewlett-Packard Company has been independently developing a similar
proposal.  HP's proposal is almost identical to Sun's but goes
beyond it to address many "corner case" areas which strongly affect
System V compatibility.
@.PP
This paper gives an overview of the relevant areas of System V 
functionality which are affected.  It then overviews how job control
is implemented in 4.2BSD and how this impacts the System V interface.
Finally, the HP-UX interface is presented and a similar overview of its
implementation is given.
@.PP
The various overviews cover how job control signals are generated, passed,
and acknowledged by the tty driver and user processes.  They also explain
how process groups are established and changed.
@.sp 1
@.NH
FUNDAMENTALS
@.PP
In the following discussion the reader is assumed to have an understanding
of several fundamental concepts found in the
@.UX
operating system.  For convenience these concepts are briefly reviewed here.
@.NH 2
Process Groups and Controlling Terminals
@.PP
Every process has a unique numeric value associated with it called
its \fIprocess ID\fP.  Every process also has a non-unique numeric value
associated with it called its \fIprocess group ID\fP.
A \fIprocess group\fP is a collection of processes having identical numeric
process group ID's.  Typically, one process in the process group will
be the \fIprocess group leader\fP.  The process group leader has a process ID
which is numerically equal to the process group ID associated with all processes
in the process group.  Typically, the process group leader is the ancestor
of all other processes in the process group.
@.PP
A process can have a \fIcontrolling terminal\fP which is usually the login
terminal of the user who created the process.  A process can obtain access
to its controlling terminal by opening the file \fI/dev/tty\fP.
All processes in the same process group typically share the same controlling
terminal.  A terminal usually has a process group ID associated with it,
called the \fItty group ID\fP.  When a user generates a keyboard signal
(e.g., by typing the interrupt character), the tty driver sends the appropriate
signal to all processes which are members of the process group indicated by
the tty group ID.
In summary,
usually, but not necessarily, all processes in the same process group share
the same controlling terminal, and the tty group ID for that terminal is
equal to the process group ID of the process group.
@.PP
For further explanation see [Roch85] and intro(2) in your favorite
@.UX
Programmer's Manual.
@.NH 2
4.2BSD Job Control
@.PP
4.2BSD job control allows users to selectively stop (suspend) the
execution of processes and continue (resume) their execution at any
later point.  This only easily works for processes which are stopped
and continued during the same login session.
@.PP
The user almost always employs this facility via the interactive interface
jointly supplied by the system tty driver and a job control shell such as
csh(1) or ksh(1).
The tty driver recognizes a user-defined
\fIsuspend character\fP which causes all current foreground processes to
stop and the user's job control shell to resume.
The job control shell provides commands which continue stopped processes
in either the foreground or background.
The tty driver will also stop a background process when it attempts to
read from or write to the users terminal.  This allows the user to finish
or suspend their foreground task without interruption and continue the
stopped background process at a more convenient time.
@.PP
To enable the system to support this,
4.2BSD job control introduces five new signals: SIGSTOP, SIGTSTP, SIGTTIN,
SIGTTOU, and SIGCONT.  The first four signals cause a process to stop unless
the signals are being caught or ignored.  SIGCONT always causes a stopped
process to continue.  (SIGCONT has no effect on processes which are not
stopped.)  SIGSTOP cannot be caught or ignored.
@.PP
The tty driver sends some of these signals to all processes in the tty
process group under the following conditions:  The driver sends SIGTSTP when
the user types the suspend or delayed suspend character.  The driver sends
SIGTTIN (SIGTTOU) when a background process attempts to read from (write to)
its controlling terminal.
SIGCONT is usually only sent by a job control shell when
the user requests that a stopped process be continued.
Of course, any signal can be sent by a user via the kill(1) command or
by a program via the kill(2) system call.
@.PP
It should be noted that these signals can be added to a
@.UX
implementation in a manner which preserves source and object code
compatibility.  A process is not required to be aware of them.  By
default the signals do "the right thing."
@.PP
For further information see [Joy80] and [UCB83].
@.sp 1
@.NH
AT&T SYSTEM V
@.NH 2
Introduction
@.PP
System V process groups closely resemble the concept of a login session.
That is, all processes spawned during the same login session tend to
belong to the same process group, and keyboard signals are typically
sent to all processes spawned from the login session.
@.NH 2
System V Process Group Handling
@.PP
In System V, the only way to alter the process group associated
with a process (p_pgrp) is via setpgrp(2).  And this can only set the process
group to equal the process ID (pid) of the process.  When this happens
the resulting process with pid = p_pgrp is called a process group leader.
Since a process's pid can never change,
once a process issues a setpgrp(2) call it irrevocably becomes
a process group leader.
@.PP
The init(1M) process spawns all other processes on the system either
directly or indirectly.  Before directly spawning a process
(after the fork(2) but before the exec(2)),
init calls setpgrp(2).
Thus all original children (not orphans) of init are forced to (irrevocably)
be process group leaders.
@.PP
When a new process is created, it is assigned a new pid but it inherits
the process group number of its parent.  Thus child processes are, by
default, not process group leaders (although they can become a process
group leader via setpgrp(2)).
@.PP
When a process group leader which has a controlling terminal (see below)
terminates, SIGHUP is sent to all processes in the same
process group.
@.PP
Further, when a process group leader terminates, all processes that
belong to this process group are altered to belong to no process group
(their p_pgrp is set to zero).
More precisely, when any process exits, all processes whose process
group (p_pgrp) equals the pid of the terminating process will have their
p_pgrp set to zero; this check succeeds only in the case of a
terminating process group leader.
@.NH 2
System V Controlling Terminals
@.PP
A terminal that is currently open by a process may also be a "controlling
terminal" for a process group.  When certain
control characters are typed on a controlling terminal, signals are 
sent by the terminal driver to all processes that belong to the process
group associated with the terminal.
@.PP
When a process becomes a process group leader (via setpgrp(2)) it
automatically loses its controlling terminal.  After this,
the first terminal (that is not already a controlling terminal)
opened by the process
is assigned to be the controlling terminal for that process.
Also, the process group associated with that terminal (t_pgrp, also known
as the tty group ID) is set
equal to the process group associated with the process group leader
(p_pgrp).
All child processes inherit the controlling terminal and
process group of their parent.
@.PP
More precisely, in System V, the process group associated with a 
terminal (t_pgrp), can be changed in the following ways:
@.IP (1)
When a terminal is opened by a process group leader (pid == p_pgrp)
that does not already have a controlling terminal,
it becomes the controlling terminal for that process group 
(t_pgrp is set equal to p_pgrp) if it is not already a controlling
terminal.
@.IP (2)
When a process group leader (pid == p_pgrp) dies, if it has a 
controlling terminal that is associated with the same process
group (t_pgrp == p_pgrp), then that terminal is disassociated from that
process group (t_pgrp is set to zero).
@.IP (3)
When the last process to have a terminal open closes that terminal,
the terminal is disassociated from its process group (t_pgrp
is set to zero).
@.NH 2
System V Typical Scenario
@.PP
This is a typical scenario for the birth and death of a process group and
its controlling terminal.
@.PP
The init(1M) process wants to enable a terminal for login.  It calls fork(2)
to create a new process and then calls
setpgrp(2) to make the process a process
group leader which also removes the process's controlling terminal.  It
then runs the getty(1M) program as the process via exec(2).
Getty opens the terminal causing it to become getty's controlling terminal
and be associated with getty's process group (t_pgrp is set to p_pgrp).
Getty replaces itself with login(1) which replaces itself with a login
shell, e.g., sh(1).
Usually no program calls setpgrp(2) and thus all descendent processes
of the login shell are in the same process group and have the same
controlling terminal; keyboard signals are sent to all processes launched
during this session.
@.PP
When a logout occurs, the login shell (which is the process group leader) 
dies and the controlling terminal is freed up (t_pgrp is set to zero) so
that it can be claimed as a controlling terminal by a subsequent getty 
respawned by init.
SIGHUP is sent to all processes in the same process group.
The process group (p_pgrp) of all descendent processes is then set to zero.
@.PP
Note that there may continue to be background processes (previously
started by the
now defunct login shell) which continue to execute but
keyboard signals will no longer be sent to these processes (since
both t_pgrp and p_pgrp equal zero).
@.sp 1
@.NH
4.2BSD
@.NH 2
Introduction
@.PP
4.2BSD process groups closely resemble the concept of a task within
a login session, where a task represents a set of processes which
are affected as a group by job control operations.
Every time a job control shell (e.g., csh) spawns either a foreground
or background command, all processes in the pipeline (and their
descendents) are placed in their own unique process group with the
first command in the pipeline being the process group leader.
@.PP
A task is in the foreground when the process group associated with the
controlling terminal for the task (t_pgrp) is equal to the process
group associated with the processes in the task (p_pgrp).  
Otherwise the task is in the background.
A job control shell moves a job between the foreground and background
by adjusting the terminal process group (t_pgrp) of the controlling
terminal.
@.PP
Note that 4.2BSD forms new process groups with process group leaders
much more often than System V usually does (every command versus
every login).
@.NH 2
4.2BSD Process Group Handling
@.PP
In 4.2BSD, the process group associated with a process (p_pgrp)
can be altered in two ways.  The first is via setpgrp(2).  4.2BSD's setpgrp(2)
is analogous to System V's setpgrp(2) except that the former can affect
processes other than the current process and can cause the affected
process to adopt a process group other than that process's process ID (pid).
Thus, unlike System V, a process can cease to be a process group leader.
@.PP
In addition to setpgrp(2), a process that is not a member of any
process group (p_pgrp == 0) will "inherit" or join the process
group associated with its controlling terminal at the time the
process is assigned a controlling terminal during open(2).
If the terminal being opened is not presently the controlling
terminal for any process group, then the process opening the
terminal will first be made a process group leader (p_pgrp will
be set to p_pid) and then the terminal will become the controlling
terminal for this new process group.  All this is done by the
tty open code.
@.PP
When a new process is created it inherits the process group of its parent.
@.PP
Unlike System V init(1M), 4.2BSD init(8) does not call setpgrp(2) when spawning
other processes.  All processes spawned by init inherit init's process
group which happens to be zero ("not a member of any process group").
This is actually crucial for assigning controlling terminals; see below.
@.NH 2
4.2BSD Controlling Terminals
@.PP
Unlike System V, a 4.2BSD process does not lose its controlling terminal
when altering its process group (via setpgrp(2)).
Also unlike System V, a 4.2BSD process that is a process group leader
(pid == p_pgrp) but which has no controlling terminal does not receive
a controlling terminal when opening a new terminal.
@.PP
A process can obtain a controlling terminal under 4.2BSD in only the
following ways:
@.IP (1)
A process can inherit a controlling terminal from its parent.
@.IP (2)
A process that is not a member of any process group (p_pgrp == 0)
can open any terminal and that terminal will become its controlling
terminal (whether or not it is already the controlling terminal for another
process).
However, this can happen in one of two ways:
@.IP
If the terminal is not already a controlling terminal (t_pgrp == 0)
then the opening process becomes a process group leader (its p_pgrp is set
equal to its pid) and the terminal becomes its controlling terminal
(t_pgrp is set to the new p_pgrp value).
@.IP
If the terminal is already a controlling terminal for another process
(t_pgrp is not zero) then the opening process joins the process group
already associated with the controlling terminal.  That is, p_pgrp is
set equal to the current t_pgrp.  Note that the opening process does
not become a process group leader, i.e., p_pgrp is not equal to its pid.
@.IP
Note that this procedure only happens during the first terminal open
for a process that was either originally spawned by init or whose
ancestor processes (all the way back to init) never altered their
process group (p_pgrp) either by opening a terminal or calling setpgrp(2).
@.PP
A terminal ceases to be a controlling terminal (t_pgrp is set to zero) under
4.2BSD in the following way:
@.IP (1)
When the last process to have a terminal open closes that terminal
then the terminal is disassociated from its process group (t_pgrp
is set to zero).
@.PP
There are two other facilities unique to 4.2BSD which affect access to
control terminals: the TIOCSPGRP ioctl(2) and vhangup(2).
@.PP
The TIOCSPGRP ioctl(2) function changes a terminal's process group (t_pgrp)
to any desired value.
It is typically used by csh(1) to control which set of processes (process
group) is in the foreground.
@.PP
The vhangup(2) function is invoked by init after
forking but before exec'ing getty.  This function removes read and
write permission for all processes (including the caller)
that have the controlling terminal
open (whether or not it is their controlling terminal).  It then sends
SIGHUP to the process group associated with the terminal (t_pgrp).
The latter action is similar to the System V functionality that sends
SIGHUP to a process group on death of the process group leader; 4.2BSD
does not do this on the death of a process group leader.
@.NH 2
4.2BSD Typical Scenario
@.PP
This is a typical scenario for the birth and death of a login, its
controlling terminal, and process groups associated with a job.
@.PP
The init(8) process wants to enable a terminal for login.
First it creates a new process via fork(2).
Then it opens the terminal which
(because the p_pgrp inherited from init is zero)
causes it to become the controlling
terminal for this process and either alters the process group (p_pgrp) of
the process to match the terminal process group (t_pgrp) if non-zero, or
alters both p_pgrp and t_pgrp to equal the process ID (pid) if t_pgrp is zero.
At this point the new process has a controlling terminal whose process group
(t_pgrp) is equal to the process's process group (p_pgrp).  However, the 
process may not be a process group leader (i.e., p_pgrp may not equal pid).
@.PP
Now the new process calls vhangup(2) to remove
access permissions for the controlling terminal from all processes (as well
as sending SIGHUP to any processes in the process group previously
associated with the terminal).
The new process then reopens the terminal to get a file descriptor with
read and 
write permissions since the vhangup(2) removed these permission from the
file descriptor returned by the previous open.
The previous file descriptor is not closed until now to prevent losing
the controlling terminal; (remember that p_pgrp for the new process is
no longer zero.)
@.PP
The new process now replaces itself with getty(8) which replaces itself
with login(1) which replaces itself with a login shell, e.g., csh(1).
Csh now begins to manipulate the process group associated with the
terminal (t_pgrp) via the TIOCSPGRP and TIOCGPGRP ioctl(2) calls and
the process group associated with its child processes (p_pgrp) via
setpgrp(2) in order to allow job control.  This happens (briefly) in the
following way:
@.PP
Csh launches a pipeline by making all programs in the pipeline be
immediate descendents of csh.  (This is different from sh which makes
all programs in the pipeline except the last be descendents of the
last program in the pipeline.)
All programs in the pipeline belong to the same process group (not the
same as csh's process group) and the first program in the pipeline is
the process group leader (its pid is equal to the process group for the
pipeline).
If the pipeline is being launched in the foreground (or moved to the
foreground) then the process group associated with the terminal (t_pgrp)
is set to the process group of the pipeline.
@.PP
When a logout occurs, the login shell dies.
Any pending SIGTTIN, SIGTTOU, and SIGTSTP signals are cleared for all 
descendent processes.
All immediate child processes are inherited as orphans by init; if any are
currently stopped then they are killed (SIGKILL).
If the exiting process is the last process that has the controlling 
terminal open then the terminal's process group (t_pgrp) is set to zero,
otherwise it is left alone.
Nothing special is done for process group leaders; in fact, login shells
are frequently not process group leaders.  (SIGHUP is not sent and the
controlling terminal is not necessarily cleared.)
@.PP
Note that there may continue to be processes (previously
started by the now defunct login shell) which continue to execute.
And that keyboard signals can still be sent to these processes under some
circumstances (specifically when the processes were in the foreground
(p_pgrp == t_pgrp) when the login shell died; this usually only happens
when the login shell is killed from another terminal via kill(1).)
Note also that this continues to be true even after a new session logs in
on the same terminal since the new login shell joins the process group
which is already associated with the terminal from the prior login.
@.NH 2
Job Control Signal Handling
@.PP
The following discussions concerning signals and kernel process
synchronization are similar to ones found in [Thom78], [Ritch79],
and [Bach79].
@.NH 3
Basic Overview
@.PP
Usually a process is either running or sleeping waiting for an event to
occur (e.g., I/O completion).  When a signal is sent to a process (either
by another process or an I/O driver) what actually occurs is that a flag
is set for the receiving (or target) process indicating that the signal
has been sent and the target process performs the actual signal operation
to itself the next time it runs.  Thus sending a signal amounts to
requesting the target process to itself perform a particular action.
If the target process is already running it is interrupted to process
the signal.  If it is runnable but not currently running then the
system merely waits for it to become the currently running process at
which point the signal is acknowledged.  If the target process
is sleeping then either
it is moved into a runnable state (if it is sleeping at an "interruptable"
priority) or it is left sleeping (at an "uninterruptable" priority) and
the signal is not acknowledged until the slept on event occurs.
@.PP
The kernel procedure which sends a signal is psignal() and is executed
by the sending process or driver.
Psignal() updates a list of pending signals for the receiving process.
If the receiving process is the currently running process and it is
executing in kernel mode then the pending signal is acknowledged
when the current system call completes.
(This is the case where the sending process and the receiving process
are the same.)
If the receiving process is the currently running process and it is
executing in user mode then a special event is generated
which causes the process to
enter the kernel and acknowledge the pending signal.
(This is the case where the sending "process" is really an interrupt
handler which, for example, is servicing an interrupt character
typed on a user's terminal.)
If the receiving process is
sleeping but not holding off signals then it is set running via wakeup();
the pending signal is acknowledged as soon as the receiving process executes.
If the receiving process is suspended in a sleep state that holds off
signals ("sleeping uninterruptably") then it is left sleeping;
the pending signal will be acknowledged after the waited for event occurs.
@.PP
The procedure which tests for a pending signal is issig() and is executed
by the receiving process.
Issig() is executed whenever the receiving process changes from kernel
mode to user mode execution; for example, at the completion of a system call.
It is also executed whenever the receiving process is awakened from
being suspended in a sleep state that does not hold off signals ("sleeping
interruptably").
@.PP
The procedure which performs the requested signal operation (e.g.,
invoking a signal handler or killing the process) is psig() and is
executed by the receiving process if issig() returns true.
@.PP
This basic structure is essentially the same in System V, 4.2BSD, and
HP-UX.  However, under 4.2BSD-style job control, these general principles
can work slightly differently:
@.PP
When processing stop signals,
the psignal() function, called by the sending process, actually stops 
the target process sometimes.  In these cases, the target process
never realizes that it received the signal or that it stopped.  
However, in other cases, psignal() performs the usual process of 
setting the flag (p_sig) requesting
that the target process stop itself the next time it runs.
@.PP
The issig() function, called by the target process, can actually stop the
target process.
@.PP
The psig() function is only called in the case where a user handler
has been provided for the job control signal.
@.PP
A more complete description of job control signal handling is contained
in the pseudocode below.
@.NH 3
psignal()
@.PP
To send SIGCONT to a target process:
@.PB
sending SIGCONT clears any pending stop signals;
if the target process is STOPPED but is also SLEEPING (p_wchan != 0)
	merely continue the process's SLEEP;

else if the target process is STOPPED and is NOT SLEEPING (p_wchan == 0)
	set the process RUNNING;
@.PE
@.PP
To send a stop signal (SIGTSTP, SIGTTIN, SIGTTOU, SIGSTOP) to a target process:
@.PB
sending a stop signal clears any pending SIGCONT;

if the target process is RUNNABLE or RUNNING
	note the pending signal in p_sig;

else if the target process is SLEEPING NON-interruptably
	note the pending signal in p_sig;

else if the target process is SLEEPING interruptably
     and IS catching the signal
	note the pending signal in p_sig and
	wakeup the process from its sleep;

else if the target process is SLEEPING interruptably
     and is NOT catching the signal
	stop the process by setting its state to SSTOP
	but leave it sleeping on its p_wchan;
	send SIGCLD to parent (if it expects BSD-style)
@.PE
@.PP
General note: sending a stop signal (other than SIGSTOP) to a child
of init causes the target process to be killed.
@.NH 3
issig()
@.PP
Issig() is called in all cases except where the process was
sleeping interruptably and was not catching the signal. 
@.PP
To acknowledge a pending SIGCONT or stop signal:
@.PB
if in the middle of a VFORK
	hold off all stop signals (pretend they don't exist yet)

else if catching the signal
	return a request to invoke user signal handler via psig()

else if SIGCONT
	do nothing  /* pretend it doesn't exist */

else /* stop signals */
	stop the process by setting its state to SSTOP
	send SIGCLD to parent (if it expects BSD-style)
	call swtch() to dispatch another process
@.PE
@.PP
General note: sending a stop signal (other than SIGSTOP) to a child
of init causes the target process to be killed.
@.NH 3
psig()
@.PP
Psig() is called whenever issig() returns an indication
that a user handler is defined for a job control signal.
Psig() merely invokes the user signal handler.
@.NH 3
wakeup()
@.PP
The fact that a process is sleeping (waiting for an event to occur)
is indicated by two process state values:  p_wchan is non-zero,
indicating the event being waited for, and the process state is SSLEEP.
@.PP
Wakeup() usually causes all processes waiting (sleeping) on a specified 
event to be awakened.  When a process is awakened two things
happen:  The process is removed from the sleep queue (p_wchan is cleared)
and it is added to the run queue.
@.PP
If, however, wakeup() discovers a process whose p_wchan matches the 
specified event but whose process state is SSTOP (stopped) then
the process is removed from the sleep queue (indicating that the
waited for even has happened) but it is not placed on the run queue.
A subsequent SIGCONT will cause it to be placed on the run queue.
@.PP
Thus it is possible to have a process which is both sleeping (p_wchan
non-zero) and stopped (process state is SSTOP rather than SSLEEP).
@.NH 3
Signal Setup via init
@.PP
When init(8) launches any process it causes the process to ignore all
the job control stop signals (SIGTSTP, SIGTTIN, & SIGTTOU).  This allows
login shells which are not job control shells to automatically ignore
the signals.  Further, all descendent processes of such a login shell
will also ignore these signals unless they explicitly enable them.
@.NH 2
Foreground/Background Processes
@.NH 3
Basic Overview
@.PP
4.2BSD job control supports the notion of a process being in the
@.I foreground
or
@.I background.
The distinction is a background process is usually forced to stop when
it attempts to perform I/O (including most control operations) on its
controlling terminal, while a foreground process is not hindered.
@.PP
Specifically, when a background process attempts to read from its controlling
terminal it is sent the SIGTTIN signal which, by default, causes it to stop.
When it attempts to write to its controlling terminal and LTOSTOP has been
enabled for the terminal, then the process is sent the SIGTTOU signal which,
by default, causes it to stop.
If, however, a background process has chosen to catch the signal, the 
specified user handler is invoked.
If the process is ignoring or masking the stop signal(s), then
the terminal I/O request returns an I/O error, EIO.
@.PP
A background process is one whose process group (p_pgrp) is not equal
to the process group of its controlling terminal (t_pgrp) (and t_pgrp
is not zero).  All other processes (including ones doing I/O to terminals
that are not their controlling terminals) are considered to be in the
foreground.
@.NH 3
Tty Driver Provisions
@.PP
To distinguish between foreground and background
programs the tty driver must perform checks on attempted I/O operations to
a process's controlling terminal.
This is done in several places.
@.PP
At the beginning of a read/write system call the tty driver checks
to see if the calling process is in the background.
If it is, then all processes in the
process group of the calling process are sent the appropriate
signal (SIGTTIN or SIGTTOU) unless the signal is masked or ignored
by the calling process.  In this case the driver returns the EIO error.
After the tty driver sends the signal, the calling process is put to
sleep waiting for the \fIlightning bolt event\fP\(dg.
@.FS
\(dg The lightning bolt event is a standard
@.UX
event which occurs frequently, for example, every second.
@.FE
This allows the calling process to receive the signal (and usually stop).
When the process returns from the sleep (usually by being continued) the
tty driver repeats the foreground/background check before proceeding with
the operation.
@.PP
When the process is in the foreground, the I/O operation proceeds.
In the case of a terminal read this usually results in the process being
put to sleep to wait for input characters to arrive.
At this point the user could type their suspend character (e.g., ^Z).
This causes the interrupt portion of the tty driver to send SIGTSTP
to the controlling terminal's process group (i.e., all processes which
are in the foreground).  In our scenario this
would include the process sleeping on terminal input, and this would
typically cause it to stop.
@.PP
When a sleeping process is stopped it is also left sleeping as well.
If, in this case, tty input characters subsequently arrived then the 
process would
be awakened.  However, because it is also stopped, it would not be
set running; it would merely be "unslept".
@.PP
At some later time the process would be continued (e.g., via a csh
"fg" or "bg" command which sends SIGCONT).
If the process had not been previously unslept it would merely continue
its sleeping; it would receive no indication that it had stopped and 
continued.
If the process had been previously unslept it would now be set running.
@.PP
When the process is set running it resumes execution in the tty driver.
Because a (potentially substantial) amount of time has elapsed and
because the process may have been stopped and restarted,
the tty driver is no longer sure whether this process is still in
the foreground.
So before checking if input characters are available, the tty driver
rechecks whether the process is in the foreground or background.
This is necessary because, in our
scenario, the stopped process could have been continued in the background
(via csh "bg").  To check this the tty driver merely repeats the
foreground/background check it made at the beginning of the system call.
@.sp 1
@.NH
SYSTEM V INCOMPATIBILITIES AND THEIR RESOLUTIONS
@.PP
Job control as implemented in 4.2BSD is incompatible with System V
semantics in some significant respects.  This section discusses
each of these incompatibilities and the resolution implemented in HP-UX
to maintain System V compatibility.
@.PP
The system interface needed to support 4.2BSD-style job control,
tailored for System V compatibility as discussed in this section,
is presented in the form of manual page excerpts in [Len86].
@.NH 2
Setpgrp(2) Changes
@.PP
Because the needed semantics of 4.2BSD setpgrp(2) conflict with the
semantics of System V setpgrp(2), the 4.2BSD setpgrp(2) function was renamed
to be setpgrp2(2).  (The choice of new name is arbitrary; setpgrp2 was chosen
in the same spirit as 4.2BSD's wait3(2).)
@.NH 2
SIGHUP Changes
@.PP
System V semantics state that when a process group leader dies, all processes
in the same process group are sent the SIGHUP signal which, by default, kills
all the processes.
@.PP
Job control shells execute a command by making all processes in the pipeline
belong to the same (brand new) process group and by making the first program
in the pipeline be the process group leader.  Typically, the first program in a
pipeline terminates before the other programs.  Under System V semantics,
this would cause the premature death of the remaining pipeline.  Because
of this, 4.2BSD does not generate SIGHUP on process group leader death.
@.PP
In order to support System V semantics and still allow job control to
function properly, HP-UX makes a distinction between a "System V process
group leader" and a "job control process group leader".  A System V 
process group leader is given System V semantics (SIGHUP is generated)
and a job control process group leader is given 4.2BSD semantics (SIGHUP
is not generated).
A process which becomes a process group leader via setpgrp(2) is considered
to be a System V process group leader.
A process which becomes a process group leader via setpgrp2(2) is considered
to be a job control process group leader.
Since the HP-UX (and System V) init(1M) program calls setpgrp(2) on behalf
of all processes it spawns, all login shells start out as System V process
group leaders.  A process must explicitly call setpgrp2(2) to deviate from
the System V semantics.
@.NH 2
SIGCLD Changes
@.PP
Under System V, SIGCLD is sent to a process whenever one of its immediate
child processes dies.
Under 4.2BSD, SIGCLD (or its variant, SIGCHLD) is also generated
when a process changes state from running to stopped.
Since a System V application would not expect to receive SIGCLD
under these new circumstances and since a job control shell would
not be able to function properly without such notification, a compatible
compromise was developed.
@.PP
The (parent) process wishing to trap SIGCLD may set a flag when calling
the HP-UX sigvector(2)\(dg
@.FS
\(dg Sigvector(2) is an HP-UX extension proposed to the IEEE P1003 [Head85]
which supports both the reliable
signal operations of 4.2BSD sigvec(2) and the conventional signal 
operations of System V signal(2).  In HP-UX, signal(2) is implemented
as a library using sigvector(2).
Note that the changes proposed here to sigvector(2) can be identically
made to 4.2BSD sigvec(2).
@.FE
\|routine to establish a signal handler.  This flag
will cause SIGCLD to be sent for stopped children, in addition to terminated
children.
A System V application using signal(2) will see the System V compatible
SIGCLD semantics.
@.NH 2
Controlling Terminal Changes
@.PP
Under System V, whenever a process group leader dies, the controlling terminal
associated with that process group (if any) is deallocated (disassociated from
that process group).
4.2BSD does not deallocate controlling terminals on process group leader death
for the following reason:
Job control shells make the lead process in every pipeline a process
group leader.  If the controlling terminal for each pipeline were deallocated
whenever the lead process terminated, then the remaining processes would
effectively become background processes (assuming they were currently in
the foreground) and would stop when any of them attempted subsequent I/O to the
terminal.
@.PP
To allow both semantics, controlling terminals are only deallocated when
a "System V process group leader" dies and not when a "job control process
group leader" dies.  (See the discussion of SIGHUP changes above.)
@.PP
However, this change leads to the following problem:
In order for a terminal to be allocated as a controlling terminal for a 
new login, it must be deallocated when the previous login terminates.
System V relies on process group leader death to deallocate controlling
terminals (since all login shells are forced to be process group leaders
by init(1M)).
This is no longer reliable since login shells could become "job control
process group leaders".  Further, not all logins are spawned directly
by init(1M); the 4.2BSD rlogin facility is a prime example.
4.2BSD solves this problem by allowing a new login to join the process
group of the controlling terminal which is still allocated from the 
previous login.  However this violates System V compatibility.
@.PP
The solution chosen was to mark a process that causes a controlling
terminal to be allocated and to deallocate the controlling terminal
whenever that process terminates.  This reliably catches logins which
are spawned either directly or indirectly from init(1M), whether they are
"System V process group leaders" or not.  Controlling terminals continue
to be deallocated on death of System V process group leaders using the
System V semantics.
@.NH 2
Security
@.PP
Several security holes exist in the 4.2BSD process group altering
mechanisms.  To plug these holes the following changes were made.
@.PP
4.2BSD setpgrp(2) allows a process to alter the process group associated
with another process to any value.
4.2BSD restricts this operation so that the
affected process must pass the same security restrictions enforced when
sending signals, or must be a descendent of the calling process.
However, this still allows a process to join a process group
already associated with another user.
To tighten this security, setpgrp2(2) was further restricted such that if the
specified new process group value is equal to the process ID (pid) or
process group ID of any existing processes, then all such processes must
pass the above security restrictions.
@.PP
Similarly, the 4.2BSD TIOCSPGRP ioctl(2) allows a terminal's process group
to be altered to any value.  This allows a user's terminal to easily become
an additional "controlling terminal" for another user's process group;
keyboard signals can be sent to the other user's processes, thus bypassing
the security enforced by kill(2).
Because of this, the TIOCSPGRP ioctl(2) was altered to enforce similar
security restrictions as setpgrp2(2).
@.PP
In System V and 4.2BSD, a process can obtain access to its controlling
terminal by opening the file \fI/dev/tty\fP.  Under System V, processes
left executing after a user's logout are allowed further access to
\fI/dev/tty\fP until the terminal it represents is reallocated as a
controlling terminal for a new login.  More specifically, \fI/dev/tty\fP
access is allowed whenever the process group ID of the leftover process
matches the process group ID of the terminal.  These IDs continue to match
immediately after logout (since both have been zeroed) until the terminal
is re-enabled for login by getty(1M).  (Note that when the new login
terminates, \fI/dev/tty\fP access is restored again to these prior processes
because the controlling terminal's process group ID is re-zeroed.)  Further,
if a process has its controlling terminal opened directly (not
via the \fI/dev/tty\fP synonym) then access is not restricted at all after
logout.
These System V semantics can constitute security problems.  However, they
are not explicitly required by the System V Interface Definition [ATT86].
@.PP
4.2BSD does nothing to hamper \fI/dev/tty\fP access for processes remaining
after logout.  The process group ID for the controlling terminal is not
altered, and, in fact, it is preserved even into the next login (since
subsequent logins join the already existing process group associated with the
terminal, if any).  These semantics also represent security problems.
However, 4.2BSD does prohibit access to the controlling terminal if it
is opened directly; this is accomplished when init(8) issues the vhangup(2)
system call.
@.PP
Although preserving the System V semantics for controlling terminal access
after logout is not deemed necessary or even recommended, it is easy to do
in the following way.
Whenever a process that allocated a controlling terminal dies, all processes
which share this controlling terminal have their process group ID zeroed.
This is analogous to, and occurs in addition to, the System V behavior of
zeroing the process group ID for all related processes when their process
group leader dies.  \fI/dev/tty\fP checks similar to System V can then
be employed.
@.NH 2
TTY Driver Considerations
@.PP
For System V compatibility, the suspend and delayed suspend characters
are defaulted to a disabled value (0377).  This means that job control
is "inactive" by default when a user logs on.  The user must explicitly
activate job control by defining either or both of these characters via
stty(1) or some similar interface.
@.PP
There should be no problem allowing 4.2BSD-style job control, as modified
here, to co-exist with System V's shell layers job control system.
(See shl(1) and sxt(7) in the System V Release 2 reference manuals.)
@.sp 1
@.NH
HP-UX
@.NH 2
Introduction
@.PP
HP-UX process groups are used in two major ways.
@.PP
System V process groups closely resemble the concept of a login session.
That is, all processes spawned during the same login session tend to
belong to the same process group, and keyboard signals are typically
sent to all processes spawned from the login session.
@.PP
Job control process groups closely resemble the concept of a task within
a login session, where a task represents a set of processes which
are affected as a group by job control operations.
Every time a job control shell (e.g., csh) spawns either a foreground
or background command, all processes in the pipeline (and their
descendents) are placed in their own unique process group with the
first command in the pipeline being the process group leader.
@.PP
A task is in the foreground when the process group associated with the
controlling terminal for the task (t_pgrp) is equal to the process
group associated with the processes in the task (p_pgrp).  
Otherwise the task is in the background.
A job control shell moves a job between the foreground and background
by adjusting the terminal process group (t_pgrp) of the controlling
terminal.
@.PP
Note that a job control shell forms new process groups with process 
group leaders
much more often than a non-job control (System V) shell usually does
(every command versus every login).
@.NH 2
HP-UX Process Group Handling
@.PP
In HP-UX, the process group associated with a process (p_pgrp)
can be altered via setpgrp(2) or setpgrp2(2).
@.PP
As in System V, setpgrp(2) can only set the process
group to equal the process ID (pid) of the process.  When this happens,
the resulting process with pid = p_pgrp is called a System V process group
leader.
@.PP
Setpgrp2(2) is analogous to setpgrp(2) except that it can affect
processes other than the current process and can cause the affected
process to adopt a process group other than that process's process ID (pid).
Setpgrp2(2) also forms job control process groups rather than System V
process groups.
Using setpgrp2(2), the calling process, or certain other processes, can either
become a job control process group leader or can cease to be a process
group leader.
@.PP
Because job control process groups are handled slightly differently
by HP-UX than System V process groups, HP-UX marks processes
that are job control process group leaders (i.e., that have
called setpgrp2(2) without subsequently calling setpgrp(2)).
@.PP
The init(1M) process spawns all other processes on the system either
directly or indirectly.  Before directly spawning a process
(after the fork(2) but before the exec(2)),
init calls setpgrp(2).
Thus all original children (not orphans) of init are forced to
start out as System V process group leaders.
@.PP
When a new process is created, it is assigned a new pid but it inherits
the process group number of its parent.  Thus child processes are, by
default, not process group leaders (although they can become a process
group leader via either setpgrp(2) or setpgrp2(2)).
@.PP
When a System V process group leader that has a controlling terminal
(see below) terminates, SIGHUP is sent to all processes in the same
process group.
Further, when a System V process group leader terminates, all processes
which belong to this process group are altered to belong to no process group
(their p_pgrp is set to zero).
@.PP
Also, whenever any process that allocated a controlling terminal terminates,
all processes that share this controlling terminal are altered to belong
to no process group (their p_pgrp is set to zero).
@.PP
When any process exits, any pending SIGTTIN, SIGTTOU, and SIGTSTP signals
are cleared from all descendent processes (not just immediate children).
@.NH 2
HP-UX Controlling Terminals
@.PP
A terminal that is currently open by a process may also be a "controlling
terminal" for a process group (collection of processes).  When certain
control characters are typed on a controlling terminal, signals are 
sent by the terminal driver to all processes which belong to the process
group associated with the terminal.  These include the job control suspend
and delayed suspend characters.
@.PP
Controlling terminals also play a role in determining whether a process
is in the foreground or background.  See FOREGROUND/BACKGROUND PROCESSES
above.
@.PP
When a process becomes a System V process group leader (via setpgrp(2)) it
automatically loses its controlling terminal.
(This does not happen for a job control process group leader, i.e. when
calling setpgrp2(2).)
After this,
the first terminal (that is not already a controlling terminal)
opened by a process that is a (System V or job control) process group leader
is assigned to be the controlling terminal for that process;
also the process group associated with that terminal (t_pgrp) is set
equal to the process group associated with the process group leader
process (p_pgrp).
All child processes inherit the controlling terminal and
process group of their parent.
@.PP
More precisely, in HP-UX, the process group associated with a 
terminal (t_pgrp), can be changed in the following ways:
@.IP (1)
When a terminal is opened by a System V or job control
process group leader (pid == p_pgrp)
that does not already have a controlling terminal,
it becomes the controlling terminal for that process group 
(t_pgrp is set equal to p_pgrp) if it is not already a controlling
terminal.
@.IP (2)
When a System V process group leader (pid == p_pgrp) dies, if it has a 
controlling terminal that is associated with the same process
group (t_pgrp == p_pgrp), that terminal is disassociated from that
process group (t_pgrp is set to zero).
@.IP (3)
When any process dies which originally caused a controlling terminal
to be created (see (1) above),
if it still has a controlling terminal,
that terminal is disassociated from its
process group (t_pgrp is set to zero).
@.IP (4)
When the last process to have a terminal open closes that terminal,
the terminal is disassociated from its process group (t_pgrp
is set to zero).
@.IP (5)
The TIOCSPGRP ioctl(2) call can explicitly change a terminal's
process group (t_pgrp) to any value within certain security restrictions.
This is used by a job control shell to change which set of processes
(process group) is in the foreground.
@.NH 2
HP-UX Typical Scenario
@.PP
This is a typical scenario for the birth and death of a login, its 
controlling terminal, and the process groups associated with a job.
@.PP
The init(1M) process wants to enable a terminal for login.  It creates a
new process via fork(2) and calls setpgrp(2) to make it a System V process
group leader which also removes its controlling terminal.  Init then runs
the getty(1M) program as the process via exec(2).
Getty opens the terminal causing the terminal to become getty's controlling
terminal
and be associated with getty's process group (t_pgrp is set to p_pgrp).
As a side effect, this process is now marked as having created a controlling
terminal; when it dies the controlling terminal will be freed for re-use.
Getty replaces itself with login(1) which replaces itself with a login
shell.
@.PP
At this point one of two scenarios typically takes place.  The login shell
is either a job control shell (e.g., csh(1)) or it is not (e.g., sh(1)).
@.PP
If the login shell is not a job control shell then things proceed much
as they do on System V.
Usually no program calls setpgrp(2) or setpgrp2(2) and thus all 
descendent processes
of the login shell are in the same process group and have the same
controlling terminal; keyboard signals are sent to all processes launched
during this session.
@.PP
If the login shell is a job control shell, then job control operations are
performed.
Csh begins to manipulate the process group associated with the
terminal (t_pgrp) via the TIOCSPGRP and TIOCGPGRP ioctl(2) calls and
the process group associated with its child processes (p_pgrp) via
setpgrp2(2) in order to allow job control.  This happens (briefly) in the
following way:
@.PP
Csh launches a pipeline by making all programs in the pipeline be
immediate descendents of csh.  (This is different from sh which makes
all programs in the pipeline except the last be descendents of the
last program in the pipeline.)
All programs in the pipeline belong to the same process group (not the
same as csh's process group) and the first program in the pipeline is
the process group leader (its pid is equal to the process group for the
pipeline).  This process is specially marked as a job control process
group leader since it was established via setpgrp2(2); this basically
prevents SIGHUP from being sent to the pipeline when the lead process dies.
If the pipeline is being launched in the foreground (or moved to the
foreground) then the process group associated with the terminal (t_pgrp)
is set to the process group of the pipeline via the TIOCSPGRP ioctl(2).
@.PP
When a logout occurs, the login shell dies.
Any pending SIGTTIN, SIGTTOU, and SIGTSTP signals are cleared for all 
descendent processes.
All immediate child processes are inherited as orphans by init; if any are
currently stopped then they are killed (SIGKILL).
Since the login shell (actually the getty before it was overlaid) created
a controlling terminal, the controlling terminal is now freed (t_pgrp
is set to zero) so that it can be claimed as a controlling terminal by
a subsequent getty respawned by init; also, all processes which share
this controlling terminal have their process group (p_pgrp) set to zero.
@.PP
When a logout occurs and
the login shell is a System V process group leader, SIGHUP is sent
to all processes in the same process group, and the process group (p_pgrp)
of all descendent processes is set to zero.
@.PP
Note that there may continue to be background processes (previously
started by the
now defunct login shell) which continue to execute but
keyboard signals will no longer be sent to these processes (since
both t_pgrp and p_pgrp equal zero).
@.sp 1
@.NH
ACKNOWLEDGEMENTS
@.PP
The following people from Hewlett-Packard contributed to the interface
design and implementation of job control for HP-UX:
Jim Barton,
Dave Decot,
Larry Dwyer,
Jeff Glasson,
Rita Hanson,
Stephen Hares,
Steve Head,
Bob Lenk,
John Marvin,
Dave Mears,
Peter Notess,
Arn Schaeffer,
Eviatar Shafrir.
@.PP
Guy Harris from Sun Microsystems made many substantive comments and suggestions
which contributed to the interface design and to this paper.
@.sp 3
@.NH
REFERENCES
@.IP [ATT86] 15
\fISystem V Interface Definition\fP, Issue 2, AT&T, 1986.
@.IP [Bach84]
M. J. Bach and S. J. Buroff, "Multiprocessor 
@.UX
Operating Systems",
\fIAT&T Bell Lab. Tech. J.\fP, \fB63,\fP No. 8 (October 1984),
pp. 1733-1749.
@.IP [Head85]
Stephen Head and Donn Terry, "Reliable Signals Proposal",
IEEE P1003 Proposal #P.042, Hewlett-Packard Co., September 11, 1985.
@.IP [Joy80]
William Joy, "An Introduction to the C Shell",
Computer Science Division, University of California
at Berkeley, November 1980.
@.IP [Len86]
David Lennert, Guy Harris, et. al.,
"System V Compatible BSD-style Job Control Facilities",
IEEE P1003 Proposal #P.047, Hewlett-Packard Co. & Sun Microsystems,
April 9, 1986.
@.IP [Ritch79]
Dennis M. Ritchie, "The
@.UX
I/O System",
\fIUNIX Programmer's Manual\fP, Seventh Edition, Volume 2b,
Bell Telephone Laboratories, Murray Hill, NJ, January 1979.
@.IP [Roch85]
Marc J. Rochkind,
\fIAdvanced
@.UX
Programming\fP,
Englewood Cliffs, N.J.: Prentice-Hall, 1985.
@.IP [Harris86]
Guy Harris, "Notes on Signal, Terminal Interface, and User/Group ID
Handling Proposals", IEEE P1003 Proposal #P.045, Sun Microsystems,
January 11, 1986.
@.IP [Thom78]
K. Thompson, "UNIX Implementation",
\fIBell System Tech. J.\fP, \fB57,\fP No. 6 (July - August 1978),
pp. 1931-1946.
@.IP [UCB83]
\fIUNIX Programmer's Manual\fP, 4.2 Berkeley Software Distribution, Virtual 
VAX-11 Version, Computer Science Division, University of California
at Berkeley, August 1983.
@.PP
@.bp
@.DS C
APPENDIX

JOB CONTROL MANUAL PAGE EXCERPTS
@.DE
@.PP
The following pages contain the
@.UX
manual pages which are effected by adding a System V compatible
implementation of 4.2BSD job control.  Note that each manual page
generally contains only that portion of text which differs from the
System V manual page of the same name.  Sometimes, unchanged text
is provided for locality reference.  Changed text lines are flagged
with change bars.
@//E*O*F jobpaper.ms//
chmod u=rw,g=rw,o=r jobpaper.ms
 
echo Inspecting for damage in transit...
temp=/tmp/shar$$; dtemp=/tmp/.shar$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
   1200   8792  53685 jobpaper.ms
!!!
wc  jobpaper.ms | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if [ -s $dtemp ]
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0


Volume-Number: Volume 7, Number 54

std-unix@ut-sally.UUCP (10/18/86)

From: pyramid!utzoo!henry (Henry Spencer)
Date: Fri, 17 Oct 86 20:18:05 CDT

Apart from my overall objections to the concept of job control, there is
one thing seriously wrong with the P1003 job control proposal as posted:
it assumes that function names are distinct in at least the first 8
characters, as witness "setpgrp" vs. "setpgrp2" and "getpgrp" vs. "getpgrp2".
Note that an X3J11-conforming C implementation need distinguish only the
first 6 characters.  I would suggest revised names for the new primitives,
perhaps "setjpgrp" and "getjpgrp", with implementations which distinguish
8 or more characters providing "setpgrp2" and "getpgrp2" names as well for
maximum compatibility with existing mistakes.

				Henry Spencer @ U of Toronto Zoology
				{allegra,ihnp4,decvax,pyramid}!utzoo!henry

Volume-Number: Volume 7, Number 70

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (10/26/86)

From: seismo!munnari!yabbie.rmit.oz!rcodi@sally.utexas.edu (Ian Donaldson)
Date: Tue, 21 Oct 86 10:39:40 EST

> From: im4u!caip!hplabs!hpda!hpisoa1!davel@sally.utexas.edu (Dave Lennert)
> Date: Thu, 9 Oct 86 14:06:30 pdt
 
>        saved process group ID
> 	     An	active process has a saved process group ID that is
> 	     set to the	saved process group ID of the parent
> 	     process at	the time of creation of	the process (via
> 	     the fork()	function).  It is reset	to the process
> 	     group ID of the process when the process successfully
> 	     calls one of the exec functions.

What is the significance of the "saved process group ID"?  How is
it different to the normal process-group-ID?  Who uses it?
 
>        In section 3.2.2.2 Description of the _exit function replace
>        the paragraph:
 
>        with:
> 
> 	     If	the process is a session process group leader, the
> 	     SIGHUP signal may be sent to each process that has	a
			   ^^^ should be replaced by the word "will"
> 	     process group ID equal to that of the calling process;
> 	     also, all such processes may have their process group
> 	     ID	set to zero.
> 
> 	     If	the implementation supports the	job control option
> 	     and if the	calling	process	has child processes that
> 	     are stopped, they will be sent SIGHUP and SIGCONT
> 	     signals.
> 

I disagree with the proposal on the handling of _exit processing for
job control.  It should be possible to not have to know in advance
that you wish to log-off and leave something running that you started
in foreground and later shifted to background.  This is a KEY feature
of job control.  

vhangup() will provide clean terminals on a bsd system,
and we have improved vhangup further to not just turn off READ/WRITE bits,
but to actually redirect the file references to /dev/null (which has
the advantage of also dropping DTR reliably). 
Infinite-loop processes don't cause problems with system-response because
they are automatically niced (something that is long-needed in UNIX systems).

I see no mention of a vhangup equivalent in this proposal segment, but
then again, I haven't seen the whole of P1003 either.

I find the SIGHUP being sent by exiting processes to sub-proceses
a plain nuisance, and it does nothing for productivity.  Nohup(1)
is effectively obsoleted by job control, since the process won't
receive signals from terminals when they are in background anyway.

One if the KEY things about job-control is that you don't have
to "know in advance" what you plan to do.  Nohup(1) requires that 
you do known in advance, and with the above proposal, nohup(1) IS
required if you want to leave jobs running when you log-off.

The SIGHUP and SIGCONT signals are only sent to processes in the
terminal process group when modem carrier disappears on a BSD system.
Children of init that are stopped are also sent SIGHUP's and SIGCONT's.
Children of init that aren't stopped aren't sent anything.

Ian Donaldson

Volume-Number: Volume 7, Number 84

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (10/26/86)

From: pyramid!decwrl!qubix!wjvax!brett
Date: Mon, 20 Oct 86 11:03:18 pdt
Organization: Watkins-Johnson Co., San Jose, Calif.

In article <6040@ut-sally.UUCP> Hentry Spencer writes:
>From: pyramid!utzoo!henry (Henry Spencer)
>Date: Fri, 17 Oct 86 20:18:05 CDT
>
>Apart from my overall objections to the concept of job control, there is
>one thing seriously wrong with the P1003 job control proposal as posted:
>it assumes that function names are distinct in at least the first 8
>characters, as witness "setpgrp" vs. "setpgrp2" and "getpgrp" vs. "getpgrp2".
>Note that an X3J11-conforming C implementation need distinguish only the
>first 6 characters.  I would suggest revised names for the new primitives,
>perhaps "setjpgrp" and "getjpgrp", with implementations which distinguish
>8 or more characters providing "setpgrp2" and "getpgrp2" names as well for
>maximum compatibility with existing mistakes.

Let's not force all variables to be distinct in the first 6 chars.  The
proper fix is to force a conforming C compiler to be more discriminating.
-------------
Brett Galloway
{pesnta,twg,ios,qubix,turtlevax,tymix,vecpyr,certes,isi}!wjvax!brett


Volume-Number: Volume 7, Number 85

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (11/02/86)

From: pyramid!nsc!hplabs!hpda!hpisoa1!davel (Dave Lennert)
Date: Wed, 29 Oct 86 10:07:47 -0800

> From: seismo!munnari!yabbie.rmit.oz!rcodi@sally.utexas.edu (Ian Donaldson)
> Date: Tue, 21 Oct 86 10:39:40 EST
> 
> What is the significance of the "saved process group ID"?  How is
> it different to the normal process-group-ID?  Who uses it?

The saved process group ID is analogous to the saved user and group ID's
in System V.  They preserve the original values the process had when
exec'd.  This allows the process to adopt a different value for one
of these ID's and later return to its original value.  Without a "saved"
value, all knowledge of the original value and of the process's rights
to use it are lost.

The saved process group ID value is necessary with job control in the
following scenario:

Root user su's to non-root user whose login shell is a job control shell
(say csh).  Csh resets its process group to a new value (it becomes a
process group leader).  When it terminates or suspends, it needs to
restore both the tty group ID (a process group ID value) and its own
process group ID back to the original values they had at entry.  (This
restores its parent to the foreground.)  Under 4.2 this is no problem
since there are no security checks for this.  Under POSIX there are
security checks based on uid's which normally are allowed since the uid of
the parent process and the csh are identical, but in our scenario would
be disallowed because the uid's don't match.  The saved process group ID
is an alternate security check which allows the above scenario.  See the
security discussion in setpgrp2() and in the POSIX termios proposal.

> > 	     If	the process is a session process group leader, the
> > 	     SIGHUP signal may be sent to each process that has	a
> 			   ^^^ should be replaced by the word "will"
> > 	     process group ID equal to that of the calling process;

"May" is used here to allow 4.2 systems to conform.  4.2 does not
send SIGHUP on process group leader death.

Note that, with a job control shell, all child processes started by
the shell are placed in a different process group than the (process
group leader) shell is in.  Thus when the shell dies, SIGHUP is not
seen by any of the children anyway.

> I disagree with the proposal on the handling of _exit processing for
> job control.  It should be possible to not have to know in advance
> that you wish to log-off and leave something running that you started
> in foreground and later shifted to background.  This is a KEY feature
> of job control.  

This key feature is preserved in the POSIX specification.  Perhaps I
don't understand your statement.

> vhangup() will provide clean terminals on a bsd system,
> and we have improved vhangup further to not just turn off READ/WRITE bits,
> but to actually redirect the file references to /dev/null (which has
> the advantage of also dropping DTR reliably). 
> I see no mention of a vhangup equivalent in this proposal segment, but
> then again, I haven't seen the whole of P1003 either.

vhangup() is indeed desirable.  It is not required in POSIX because it is 
not supported on System V and, indeed, breaks System V compatiblity.
(See my job control paper that was posted in mod.std.unix recently.)

> Children of init that are stopped are also sent SIGHUP's and SIGCONT's.

More correctly, at the time a stopped process is inherited by init (due 
to its parent's death), it is sent SIGHUP and SIGCONT.  POSIX has this
too; see the _exit part of the job control specification.

> Infinite-loop processes don't cause problems with system-response because
> they are automatically niced (something that is long-needed in UNIX systems).

Note that this is NOT desirable on, e.g., realtime systems where that
long running process may be critical.  I'm also getting tired of having
my rwhod reniced automatically.

    Dave Lennert                ucbvax!hpda!davel               [UUCP]
    Hewlett-Packard - 47UX      ihnp4!hplabs!hpda!davel         [UUCP]
    19447 Pruneridge Ave.       hpda!davel@ucb-vax.ARPA         [ARPA]
    Cupertino, CA  95014        (408) 447-6325                  [AT&T]


Volume-Number: Volume 8, Number 12

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (11/03/86)

From: guy@sun.com (Guy Harris)
Date: Mon, 3 Nov 86 00:39:00 PST

> > > 	     If	the process is a session process group leader, the
> > > 	     SIGHUP signal may be sent to each process that has	a
> > 			   ^^^ should be replaced by the word "will"
> > > 	     process group ID equal to that of the calling process;

> "May" is used here to allow 4.2 systems to conform.  4.2 does not
> send SIGHUP on process group leader death.

4.2 also doesn't have the notion of a "session process group leader".
However, when the moral equivalent of a "session process group leader" dies
in 4.2, 99.99% of the time it's a login shell, and "init" proceeds to do a
"vhangup" which - sends a SIGHUP!

> vhangup() is indeed desirable.  It is not required in POSIX because it is 
> not supported on System V and, indeed, breaks System V compatiblity.

Only if you define "System V compatibility" as "behaves exactly the same as
some particular implementation of System V".  "vhangup" does two things; it
sends a SIGHUP to the process group of the terminal in question (which is,
in fact, similar to what S5 does automatically) and it invalidates file
descriptors that refer to the terminal.

Some System V implementations do not do this, although they *do* clear the
terminal's process group, which causes all subsequent references to that
terminal through "/dev/tty" to get an error.  As such, the evidence
indicates that the reason they don't generally invalidate references to the
controlling terminal is *not* that they intended to leave such references
valid, but that they just didn't bother.

The only programs *I* can think of that would want to be able to reference
the terminal they were started from, even after the user who started them
logged out, are not the sort of programs I would like to have running on any
machine I'm involved with.  They tend to be called things like "Trojan
horses".

Volume-Number: Volume 8, Number 20

std-unix@ut-sally.UUCP (Moderator, John Quarterman) (11/05/86)

From: seismo!munnari!yabbie.rmit.oz!rcodi@sally.utexas.edu (Ian Donaldson)
Date: Tue, 4 Nov 86 09:05:35ligt 

> From: pyramid!nsc!hplabs!hpda!hpisoa1!davel (Dave Lennert)
> Date: Wed, 29 Oct 86 10:07:47 -0800

I spoke about HUP's sent when an _exit is done, not realising at the time
that it is only done by a sesion-group leader, and only to
the same process-group, obviously (it is now) excluding those
processes running in background.

> This key feature is preserved in the POSIX specification.  Perhaps I
> don't understand your statement.

I withdraw the statement.

In the same article, I wrote: 

> > vhangup() will provide clean terminals on a bsd system,
> > and we have improved vhangup further to not just turn off READ/WRITE bits,
> > but to actually redirect the file references to /dev/null (which has
> > the advantage of also dropping DTR reliably). 
> 
> vhangup() is indeed desirable.  It is not required in POSIX because it is 
> not supported on System V and, indeed, breaks System V compatiblity.

I forgot to add the other advantage of my vhangup(), in that
any read's by processes from the terminal return EOF rather than
a read-error, and any writes go to the bit-bucket, rather than
producing a write-error.  This is very desirable in stuations where
you have started something in foreground (eg: make, without redirecting I/O) and
you want it to -complete- in background, rather than crash because
it cannot write diagnostics or output...
Of course, you cannot -see- the output, but that is another topic
(along the lines of login-suspension - see ravings in net.unix-wizards
about 6 months ago).

Some programs of course would need to be trained to not repeatedly
read beyond EOF assuming somebody is hitting ^D, otherwise they
will do-so forever.  Berkeley 4.2bsd Csh and Mail already have been
trained, and exit if a certain large number of consecutive EOF's are read.
There are probably others.
We have not felt need to modify any more programs, though there is the stray
program that just sits there all day, once a fortnight perhaps.
Readnews seems to be an often offendor (2.10.3).

I also wrote:

> > Infinite-loop processes don't cause problems with system-response because
> > they are automatically niced (something that is long-needed in UNIX 
> > systems).
> 
> Note that this is NOT desirable on, e.g., realtime systems where that
> long running process may be critical.  I'm also getting tired of having
> my rwhod reniced automatically.
> 
>     Dave Lennert                ucbvax!hpda!davel               [UUCP]

Granted, it probably -isn't- desirable at some sites, or perhaps even
some particular users at certain sites, but it is necessary for
any site that has lots of cpu-intensive tasks mixed in with lots
of heavily interactive (eg: vi) sessions.

The auto-nicing that I have seen in 4.2 (not sure who added it) whereby
a process gets niced by 1 every 40 cpu seconds until the nice reaches +15
is NOT the sort of thing I am talking about.  The obvious problem with
this algorithm is that it makes no distinctions on what it nices -
it nices compiles (ok, good), but it also nices vi (bad), and eventually
nices the shell (worse, as everything you start inherits the nice
from the shell).  It also makes no distinction on -who- it nices;
except that root is never niced (neither are other users, provided
they are running at elevated priority).  This means that all non-root owned
daemons get niced also.

I experimentally implemented a smarter, but still very simple auto-nicing
algorithm that works well here nearly all of the time:  it is an
extension of the one above, except that interactive processes are
identified very simply by the fact that they do tty input (sounds logical).

A process is only niced if it consumes N cpu seconds since last doing
some tty input (we have N set small, to 5 cpu seconds). 
This means that an interactive shell is rarely ever
niced, and vi always has a good response time regardless of what
else is going on in the system (unless you're doing complicated
length string searches or the like).  Another "quick hack" allowed
all uid's less-than a certain number (say 2) to be immue to
auto-nicing - this got around the daemon problem, altough very
unelegantly.

The kernel mods were trivial, amounting to less than a screenful
of code all-up.  In a nutshell it was one mod to clock.c 
(kern_clock.c for 4bsd), to increment the nice if the conditions
warrant it; and another mod to ttyread() to reset the nice
and the accumulated cpu time since the last ttyread().

I have watched people breath discontent over the net with vi's response time, 
and all the hack's that they've tried (including a suid root pre-elevate-nice 
command).  Vi is only mentioned because it is common to almost all
systems.  The problem is much deeper than just vi.

Any system that treats non-interactive jobs the same as interactive jobs
is sure to have a rotten response-time.  Interactive jobs are not
jobs that are just "associated" with a terminal either.  People
expecting to do half-hour compiles from the terminal soon learn
that there is no advantage in doing-so, and it is better to come back
later and free up the terminal for somebody else to use (productively).

> Note that this is NOT desirable on, e.g., realtime systems where that
> long running process may be critical.  

Perhaps, but then my version of auto-nice may solve most of such
problems anyway.  If the program on the real-time system communicates
with other than tty's in an "interactive" fashion, then this could be 
incorporated into the algorithm quite easily.  Lots of things could be 
incorporated into the algorithm - such as a per-user nice-rate and
nice-limit.

People will never learn - just telling them to "nice" their jobs
rarely works.  They either forget to, or just don't do it on principle.

SVR2 has no way of renicing a job other than restarting it
(counter-productive), and telling somebody to change their nice on the
humungous compile they just started after they've left and gone home is
also often very difficult (read impossible), leaving a very slow
system.

Vi and similar programs on our systems nearly always have a
good response time - the times that they don't would most probably
be attributed to excess paging and swapping activity and filesystem I/O.

> I'm also getting tired of having
> my rwhod reniced automatically.

Maybe it wouldn't be with the algoritm I mentioned (I've never used
rwhod so I can't answer that).

At least auto-nicing of some variety I have mentioned should
be provided as a standard -option-.  Those who don't like it
can turn it off, but I'll bet your boots that they will be
in a minority once they've tried it.  Not having the option
at all is not very nice (excuse the pun :-).

Ian Donaldson

Volume-Number: Volume 8, Number 37

std-unix@ut-sally.UUCP (Guest Moderator, John B. Chambers) (11/17/86)

References:


>From nsc!hplabs!hpda!hpisoa1!davel@pyramid.UUCP Wed Nov 12 16:57:34 1986
Cc: gorodish!guy@sun.UUCP
Date: Wed, 12 Nov 86 10:42:53 -0800

> guy@sun.com (Guy Harris) writes:
> > vhangup() is indeed desirable.  It is not required in POSIX because it is 
> > not supported on System V and, indeed, breaks System V compatiblity.
> 
> Only if you define "System V compatibility" as "behaves exactly the same as
> some particular implementation of System V".  

It is true that vhangup() does not break any documented behavior in 
System V or the SVID.  However, the System V implementations I am familiar 
with (mainly ATT VAX releases) allow access to open login tty file 
descriptors after logout (/dev/tty is the exception).

Again, vhangup() is, in my opinion, preferable for security reasons.  I
do not consider the alternate behavior present in at least some System V
ports worth requiring.  

> "vhangup" does two things; it
> sends a SIGHUP to the process group of the terminal in question (which is,
> in fact, similar to what S5 does automatically) and it invalidates file
> descriptors that refer to the terminal.
> 
> Some System V implementations do not do this, ...

I'm curious; could you list some of the System V implementations which 
disallow access to the login tty (via, e.g., stdout, not /dev/tty) after
logout?  I.e., System V's that have vhangup()-like behavior?

-Dave Lennert   HP   ihnp4!hplabs!hpda!davel


Volume-Number: Volume 8, Number 55

std-unix@ut-sally.UUCP (Guest Moderator, John B. Chambers) (11/17/86)

References:


>From nsc!hplabs!hpda!hpisoa1!davel@pyramid.UUCP Fri Nov 14 22:04:25 1986
Date: Fri, 14 Nov 86 14:40:04 -0800

> From: ihnp4!iwtpu!katzung (Brian Katzung)
> Date: Sat, 8 Nov 86 14:59:33 CST
> 
>      The wait3 system call has provisions for informing the parent when a
> child is suspended, but not when it resumes.  Thus, if an agent other than
> the parent resumes the child, the parent doesn't know about it.  This is
> rare, but not unimaginable.  I've had applications that could have been
> enhanced if the mechanism were "balanced".

You'd also want to sent SIGCLD under these circumstances, to be complete.

We actually breadboarded exactly this internally at HP.  We decided not
to include it in our product or in our POSIX proposal.  This is because
we wanted to provide an interface that is capable of supporting a 4.2
compatible interface on top of it.  This would require a way to turn off
these enhancements.  E.g., the proposal already contains the following:

	- send SIGCLD on child death		[Sys V compatible]
	- send SIGCLD on child death or stop	[4.2 compatible]

We didn't want to add:

	- send SIGCLD on child death or stop or continue

Similarly for wait3() [now known as wait2()].

I'm not saying this additional functionality isn't useful.  I just feel
that it is not so useful that I wanted to further complicate the
interface for it.

Also note that we wanted to provide an interface that could be easily
implemented on top of existing 4.2.

Anyway, that was our reasoning.

-Dave Lennert   HP   ihnp4!hplabs!hpda!davel


Volume-Number: Volume 8, Number 56