Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ jobs(3) — DG/UX 4.30

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

csh(1)

ioctl(2)

killpg(2)

setpgrp(2)

sigsys(2)

wait3(2)

sigset(3)

tty(4)



     jobs(3)                    DG/UX 4.30                     jobs(3)



     NAME
          jobs - summary of job control facilities in DG/UX

     SYNOPSIS
          #include <sys/sgtty.h>
          #include <signal.h>
          #include <sys/resource.h>
          #include <sys/time.h>
          #include <wait.h>

          int fildes, signo;
          int pid, pgrp;
          union wait status;
          int options;
          struct rusage ru;

          ioctl(fildes, TIOCSPGRP, &pgrp)
          ioctl(fildes, TIOCGPGRP, &pgrp)

          setpgrp2(pid, pgrp)
          getpgrp2(pid)
          killpg(pgrp, signo)

          sigset(signo, action)
          sighold(signo)
          sigrelse(signo)
          sigpause(signo)
          sigsys(signo, action)

          wait3(&status, options, &ru)

     DESCRIPTION
          The facilities described here support the job control
          implemented in csh(1) and may be used in other programs to
          provide similar facilities.

          For descriptions of the individual routines, see SEE ALSO
          below.  This section describes the facilities in general.

          Terminal arbitration mechanisms

          The job control mechanism works by associating with each
          process a number called a process group; related processes
          (e.g. in a pipeline) are given the same process group.  The
          system assigns a single process group number to each
          terminal.  Processes running on a terminal are given read
          access to that terminal only if they are in the same process
          group as that terminal.

          Thus, a command interpreter may start several jobs running
          in different process groups and arbitrate access to the
          terminal by controlling which, if any, of these processes is



     Licensed material--property of copyright holder(s)         Page 1





     jobs(3)                    DG/UX 4.30                     jobs(3)



          in the same process group as the terminal.  When a process
          outside the process group of the terminal tries to read from
          the terminal, all members of the process group of the
          process receive a SIGTTIN signal.  This usually stops them
          until they are continued with a SIGCONT signal.  (See
          sigsys(2) for a description of these signals; see tty(4) for
          a description of process groups.)

          If a process is not in the process group of the terminal,
          and it tries to change the terminal's mode, the process
          group of that process is sent a SIGTTOU signal, causing the
          process group to stop.  A similar mechanism is (optionally)
          available for output, causing processes to block with
          SIGTTOU when they try to write to the terminal while not in
          its process group; this is controlled by the LTOSTOP bit in
          the tty mode word. LTOSTOP is  enabled by stty tostop and
          disabled (the default) by stty-tostop.  (The LTOSTOP bit is
          described in tty(4)).

          How the shell manipulates process groups

          An interactive shell first establishes its own process group
          and a process group for the terminal; this keeps other
          processes from being stopped while the terminal is under its
          control.  The shell then assigns a distinct process group to
          each job it creates.  When a job is to be run in the
          foreground, the shell gives the terminal to the process
          group of the job using the TIOCSPGRP ioctl (See ioctl(2) and
          tty(4)).  When a job stops or completes, the shell reclaims
          the terminal by resetting the terminal's process group to
          that of the shell, using TIOCSPGRP again.

          Shells running shell scripts or running non-interactively do
          not manipulate process groups of jobs they create.  Instead,
          they leave the process group of sub-processes and the
          terminal unchanged.  This assures that if any sub-process
          they create blocks for terminal I/O, the shell and all its
          sub-processes will be blocked (since they are a single
          process group).  The first interactive parent of the non-
          interactive shell can then be used to deal with the
          stoppage.

          Processes whose parents have exited, and descendants of
          these processes, are protected by the system from stopping,
          since there can be no interactive parent.  Rather than
          blocking, reads from the control terminal return end-of-file
          and writes to the control terminal are permitted (i.e.,
          LTOSTOP has no effect for these processes.)  Similarly
          processes that ignore or hold the SIGTTIN or SIGTTOU signal
          are not sent these signals when accessing their control
          terminal; if they are not in the process group of the
          control terminal, reads simply return end-of-file.  Output



     Licensed material--property of copyright holder(s)         Page 2





     jobs(3)                    DG/UX 4.30                     jobs(3)



          and mode setting are also allowed.

          Before a shell suspends itself, it places itself back in the
          process group in which it was created. It then sends this
          original group a stopping signal, stopping the shell, and
          any other intermediate processes, back up to an interactive
          parent.  The shell also restores the process group of the
          terminal when it finishes; the process that resumes might
          not have control of the terminal otherwise.

          Naive processes

          A naive process does not alter the state of the terminal,
          and does no job control. It can usually invoke subprocesses
          safely, even if it has shell escapes or invokes other
          processes.  If such a process issues a system(3) call and
          this command is then stopped, both of the processes will
          stop together.  Thus simple processes need not worry about
          job control.

          Processes that modify the terminal state

          When first setting the terminal into an unusual mode, the
          process should check, with the stopping signals held, that
          it is in the foreground.  It should then change the state of
          the terminal, and set the catches for SIGTTIN, SIGTTOU and
          SIGTSTP.  The following is a sample of the code that will be
          needed, assuming that unit 2 is known to be a terminal.

               int  tpgrp;
               ...

          retry:
               sigset(SIGTSTP, SIGHOLD);
               sigset(SIGTTIN, SIGHOLD);
               sigset(SIGTTOU, SIGHOLD);
               if (ioctl(2, TIOCGPGRP, &tpgrp) != 0)
                    goto nottty;
               if (tpgrp != getpgrp(0)) { /* not in foreground */
                    sigset(SIGTTOU, SIGDFL);
                    kill(0, SIGTTOU);
                    /* job stops here waiting for SIGCONT */
                    goto retry;
               }
               ...save old terminal modes and set new modes...
               sigset(SIGTTIN, onstop);
               sigset(SIGTTOU, onstop);
               sigset(SIGTSTP, onstop);

          SIGTSTP is ignored in this code to prevent our process from
          being moved from the foreground to the background while
          checking if it is in the foreground.  The process holds all



     Licensed material--property of copyright holder(s)         Page 3





     jobs(3)                    DG/UX 4.30                     jobs(3)



          the stopping signals in this critical section so that no
          other process in our process group can block us on one of
          these signals in the middle of our check.  (This code
          assumes that the command interpreter will not move a process
          from foreground to background without stopping it; if it
          did, we could not make the check correctly.)

          The signal-handling routine should clear the catch for the
          stop signal and kill(2) the processes in its process group
          with the same signal.  The statement after this kill will be
          executed when the process is continued with SIGCONT.

          Thus the code for the catch routine might look like:

               ...
               sigset(SIGTSTP, onstop);
               sigset(SIGTTIN, onstop);
               sigset(SIGTTOU, onstop);
               ...

          onstop(signo)
               int signo;
          {
               ... restore old terminal state ...
               sigset(signo, SIGDFL);
               kill(0, signo);
               /* stop here until continued */
               sigset(signo, onstop);
               ... restore our special terminal state ...
          }

          This routine can also simulate a stop signal.

          If a process does not need to save and restore state when it
          is stopped, but wishes to be notified when it is continued
          after a stop, it can catch the SIGCONT signal; the SIGCONT
          handler will be run when the process is continued.

          Processes that lock data bases (such as the password file)
          should ignore SIGTTIN, SIGTTOU, and SIGTSTP signals while
          the data bases are being manipulated.  While a process is
          ignoring SIGTTIN signals, reads that would normally have
          hung will return end-of-file; writes that would normally
          have caused SIGTTOU signals are instead permitted while
          SIGTTOU is ignored.

          Interrupt-level process handling

          Sigset(3) lets you handle process state changes as they
          occur. It provides an interrupt-handling routine for the
          SIGCHLD signal, a signal that occurs whenever the status of
          a child process changes.  You establish a signal handler as



     Licensed material--property of copyright holder(s)         Page 4





     jobs(3)                    DG/UX 4.30                     jobs(3)



          follows:

               sigset(SIGCHLD, onchild);

          The shell or other process then waits for a change in child
          status with code like this:

          recheck:
               sighold(SIGCHLD);        /* start critical section */
               if (no children to process) {
                    sigpause(SIGCHLD);  /* release SIGCHLD and pause */
                    goto recheck;
               }
               sigrelse(SIGCHLD);       /* end critical region */
               /* now have a child to process */

          Here, sighold temporarily blocks the SIGCHLD signal while
          the data structures are checked for a child to process.  If
          we didn't block the signal, we would have a race condition;
          the signal might corrupt our decision by arriving shortly
          after we had finished checking the condition but before we
          paused.

          If we need to wait, we call sigpause, which automically
          releases the hold on the SIGCHLD signal and waits for a
          signal to occur by starting a pause(2).  Otherwise, we
          simply release the SIGCHLD signal and process the child.

          Important: a long-standing bug in the signal mechanism has
          been fixed.  The bug lost a SIGCHLD signal if it occurred
          while the signal was blocked.  This is because sighold uses
          the SIG_HOLD signal set of sigsys(2) to prevent the signal
          action from being taken without losing the signal.
          Similarly, a signal action set with sigset has the signal
          held while the action routine is running, much as the
          interrupt priority of a processor is raised when a device
          interrupt is taken.

          In this interrupt-driven style of termination processing,
          wait calls must not block when they retrieve status in the
          SIGCHLD signal handler.  This is because a single invocation
          of the SIGCHLD handler may indicate an arbitrary number of
          process status changes: signals are not queued.  This is
          similar to the case in a disk driver where several drives on
          a single controller may report status at once, while only
          one interrupt is taken.

          It is even possible that no children will be ready to report
          status when the SIGCHLD handler is invoked, if the signal
          was posted while the SIGCHLD handler was active, and the
          child was noticed due to a SIGCHLD initially sent for
          another process.  This causes no problem, since the handler



     Licensed material--property of copyright holder(s)         Page 5





     jobs(3)                    DG/UX 4.30                     jobs(3)



          will be called whenever there is work to do; the handler
          just has to collect all information by calling wait3 until
          no more information is available.  Further status changes
          are guaranteed to be reflected in another SIGCHLD handler
          call.

          Restarting system calls

          In older versions of UNIX, slow system calls were
          interrupted when signals occurred, returning EINTR.  The new
          signal mechanism sigset(3) normally restarts such calls
          rather than interrupting them.  To summarize:  pause and
          wait return error EINTR (as before), ioctl and wait3
          restart, and read and write restart unless some data was
          read or written; in that case, they return indicating how
          much data was read or written.  In programs that use the
          older signal(2) mechanisms, all of these calls return EINTR
          if a signal occurs during the call.

     SEE ALSO
          csh(1), ioctl(2), killpg(2), setpgrp(2), sigsys(2),
          wait3(2), sigset(3), tty(4).

































     Licensed material--property of copyright holder(s)         Page 6



Typewritten Software • bear@typewritten.org • Edmonds, WA 98026