next up previous contents index
Next: Creating Processes Up: The OS Interface: Processes Previous: More Standard Declarations

Sending and Handling Signals

 

This subsection describes the procedures for sending signals to other processes and for handling signals. It also enumerates all the possible signals and their default behavior.

     

TYPE
  SignalOrNone =
    (SigNone, SigHUp, SigInt, SigQuit, SigIll, SigTrap,
     SigIOT, SigEMT, SigFPE, SigKill, SigBus, SigSegV,
     SigSys, SigPipe, SigAlrm, SigTerm, SigUrg, SigStop,
     SigTStp, SigCont, SigChld, SigTTIn, SigTTOu, SigIO,
     SigXCPU, SigXFSz, SigVTAlrm, SigProf, SigWinCh, Sig29,
     SigUsr1, SigUsr2);
  Signal = [SigHUp .. SigUsr2];

  SignalOrNone enumerates the names of all the signals; there are 31 different named signals (not including SigNone). The definition of Signal is consistent with the numbering of signals in Ultrix 1.1 and 2.0 (see sigvec(2)). However, many of these signals should not be used by OS clients because OS provides different mechanisms for dealing with the underlying conditions. It is highly recommended that only the following signals be used:

       

  Send Handle  
Name ok? ok? Usage
SigHUp No Yes Modem carrier has dropped
SigInt Yes Yes User changed his mind (Control-C)
SigQuit Yes Yes User wants core image (Control-\)
SigKill Yes No Unconditional termination
SigTerm Yes Yes General software termination signal
SigStop Yes No Unconditional stop
SigTStp Yes Yes User wants to stop (Control-Z)
SigCont Yes Yes Restart stopped process
SigTTIn No Yes Read by background process
SigTTOu No Yes Write by background process
SigUsr1 Yes Yes User-defined signal (System V)
SigUsr2 Yes Yes User-defined signal (System V)
Sending other signals to a process can confuse the process, because of the Ultrix semantics associated with those signals. Attempting to handle other signals is deprecated because OS and Topaz provide more appropriate mechanisms. (The Ultrix implementation of OS disallows handling most other signals; the Taos implementation may be changed to match.)

                                                      Topaz converts hardware traps to exceptions defined in the System and Trap interfaces rather than converting them to the signals SigIll, SigIOT, SigEMT, SigFPE, SigBus, and SigSegV, as Ultrix does. Topaz reserves the hardware breakpoint trap for the debugger rather than converting it to SigTrace. OS raises exceptions for the synchronous events that Ultrix converts to the signals SigSys and SigPipe. OS doesn't provide the Ultrix interval timing facilities that send SigAlrm, SigVTAlrm, and SigProf; instead clients can program their own facilities using the Thread and Time interfaces. OS doesn't send SigChld or SigIO because a client can fork an extra thread to wait for the event (child state change or asynchronous I/O); this will apply to SigUrg if sockets are implemented. OS doesn't provide the Ultrix resource limit facilities that send SigXCPU and SigXFSz. OS doesn't provide the Ultrix 2.0 window size change feature that sends SigWinCh. Sig29 is reserved for future standardization.

   

PROCEDURE SendSignal(
    pid: PID;
    signal: SignalOrNone;
    euser: User := NIL)
  RAISES {Error}; (* NotSuperUserEC, BadPIDEC, NotOwnerEC *)

PROCEDURE SendSignalToGroup(
    pgrp: PGRP;
    signal: SignalOrNone;
    euser: User := NIL)
  RAISES {Error}; (* NotSuperUserEC, BadPIDEC, NotOwnerEC *)

          SendSignal sends a signal to the process with a specified process identifier; specifying pid equal to NullPID means to use the process identifier of the calling process. (Note that the conventions obeyed by the Ultrix kill kernel call for a pid of 0 or -1 do not apply to SendSignal.) SendSignalToGroup sends a signal to all the processes in a specified process group; specifying a process group identifier equal to NullPID means to send to all the processes in the group of the calling process (including the calling process itself).

  Sending SigNone is a way to check the validity of a process identifier: normal error checking is done, but no signal is actually sent.

    The sender and receiver must have the same effective user name, unless either the sender is the super-user, or the signal is SigCont and the sender is an ancestor of the receiver. NotOwnerEC is raised if none of these conditions are satisfied.

BadPIDEC is raised if no process has the process identifier passed to SendSignal or the process group identifier passed to SendToGroup.

SendSignal and SendSignalToGroup interpret the euser parameter the same way Open does.

 

TYPE
  SignalState = (SignalDefault, SignalIgnore, SignalHandle);

  A signal state represents the intention by a process with respect to a particular signal to handle the signal, to ignore the signal, or to accept the default action for that signal.

  

PROCEDURE SetMySignalState(
    signal: Signal;
    state: SignalState)
    : SignalState
  RAISES {Error} (* BadStateForSignalEC *);

    SetMySignalState allows a process to declare its intention with respect to a specified signal. It returns the previous intention.

      SetMySignalState raises BadStateForSignalEC if an attempt is made to handle or ignore a signal other than SigHUp, SigInt, SigQuit, SigPipe, SigTerm, SigTStp, SigCont, SigTTIn, SigTTOu, SigXCPU, SigWinCh, Sig29, SigUsr1, or SigUsr2. It raises BadStateForSignalEC if an attempt is made to ignore SigCont. Requiring SigKill and SigStop to be defaulted provides a reliable way to terminate or stop an errant process. Disallowing SigCont to be ignored ensures that a stopped process can be continued.

      As mentioned in Section 2.9, page [*], there are several possible default actions that can occur when a signal arrives for a process and the signal state is SignalDefault: to ignore the signal, to stop execution of the process temporarily, to continue execution of the process after such a temporary stop, or to terminate the process. If a signal is ignored (either because the signal state is SignalIgnore or because the signal state is SignalDefault and the default action for that signal is to ignore it), it is as if the signal had never been sent. Stopping and continuing processes is discussed in Section 2.11, page [*]. Terminating processes is discussed in Section 5.4, page [*].

 Which of the default actions actually occurs depends on the identity of the signal:

Ignore:
SigUrg, SigChld, SigIO, SigWinCh.
Terminate:
SigHUp, SigInt, SigKill, SigPipe, SigAlrm, SigTerm, SigXCPU, SigXFSz, SigVTAlrm, SigProf, Sig29, SigUsr1, SigUsr2.

Terminate with core image:
SigQuit, SigIll, SigTrap, SigIOT, SigEMT, SigFPE, SigBus, SigSegV, SigSys.

Stop:
SigStop, SigTStp, SigTTIn, SigTTOu.

Continue:
SigCont.

                  There is a special case involving the stop signals: if a process is an orphan, then only SigStop will stop it; the default action for SigTStp, SigTTIn, and SigTTOu is to terminate the process. The reason for this is that in the typical usage of stop signals in conjunction with job control, it is up to the parent to continue a stopped child (see Section 2.11, page [*]). An orphan would be stopped forever, so it is terminated instead.

It should be noted that signal states are inherently of process-wide significance. It is up to the application to provide its own synchronization if it dynamically alters signal state settings.

     

TYPE
  Signals = BITS 32 FOR SET OF Signal;

CONST
  AllSignals = Signals{SigHUp .. SigUsr2};

PROCEDURE WaitForSignal(allowed: Signals): Signal
  RAISES {Error, Alerted}; (* BadStateForSignalEC *)

  WaitForSignal waits until one of the signals in the allowed set becomes pending (by being sent to this process), then makes the signal not pending and returns its identity. If several signals in the allowed set are pending, it is unpredictable which of them WaitForSignal will choose. Similarly if a signal becomes pending and that signal is in the allowed sets of several threads that have called WaitForSignal, it is unpredictable which thread will be unblocked. WaitForSignal raises BadStateForSignalEC if any signal in the allowed set is not in the state SignalHandle, since it could never become pending. WaitForSignal is alertable.

      Ultrix note: The priority of the thread calling WaitForSignal must be higher than that of any compute-bound thread. See GetPriority and SetPriority in the ThreadFriends interface.

Taos note: Since the Firefly thread scheduler implements time-slicing, the priority of the thread calling WaitForSignal must be at least as high as that of any compute-bound thread.


next up previous contents index
Next: Creating Processes Up: The OS Interface: Processes Previous: More Standard Declarations
Paul McJones
8/28/1997