A signal is an asynchronous notification of an event.
A signal is said to be generated for (or sent to) a process
when the
event associated with
that signal first occurs.
Examples of such events include hardware faults,
timer expiration, terminal activity,
and the invocation of the
kill( ),
sigsend( ),
or other related system calls.
In some circumstances,
the same event generates signals for multiple processes.
Delivery of a signal
A signal is said
to be delivered to a process
when the appropriate action for
the process and signal is taken.
During the time between the generation of a signal and its delivery,
the signal is said to be pending; see
sigpending(S).
Generation of a signal
which is already pending for the process
has no detectable effect;
the signal remains pending
and only one instance of the signal will be delivered.
Ordinarily, this interval cannot be detected by an application.
A signal can, however, be blocked from delivery.
Signals are flags and do not queue up neatly.
Sending a signal to a process
raises a flag in that process.
Sending the same signal a second time,
before the first signal has been delivered,
has no further effect;
the process has no way to tell
that the signal was raised multiple times.
If multiple different signals are raised before any are delivered,
the system does not guarantee any particular delivery order.
Signal mask
Each process has a signal mask
that defines the set of signals
that are currently blocked from delivery to it;
see
sigprocmask(S),
sigaction(S),
and
sighold(S).
The signal mask for a process
is initialized from that of its creator.
If the action associated with a blocked signal is anything
other than to ignore the signal, and if that signal
is generated for the process, the signal remains
pending until either it is unblocked or the signal's disposition
requests that the signal be ignored.
If the
signal disposition of a blocked signal requests that the
signal be ignored, and
if that signal is generated for the process, the signal is discarded
immediately upon generation.
Disposition of a signal
A signal's ``disposition'' is the action
the process will take when it receives this signal.
Each signal has a default action,
which is the action to be taken
if the process does not specify a disposition.
A process can
specify a system action other than the default
to be taken in response to each signal sent to it.
The exceptions to this are SIGKILL and SIGSTOP,
which cannot be caught, ignored, or blocked;
the default dispositions always happen.
The determination of which action is taken in response to a signal
is made at the time the signal is delivered, allowing
for any changes since the time of generation.
This determination is independent of the means by which the signal
was originally generated.
Summary of signals with SIG_DFL actions
The operating system defines a set of supported signals
with default actions for each.
These default actions are taken
unless the process defines different actions
for a particular signal.
The following table summarizes
the signals that are defined for SCO OpenServer,
showing their number, the default disposition,
and a brief description.
The following section gives more details
about the default dispositions.
The SIGCLD, SIGIOT, and SIGIO names
are defined for backward compatibility.
Use their current equivalents
(SIGCHLD, SIGABRT,
and SIGPOLL, respectively)
in new applications.
The signal table summarizes the default action
(in other words,
the action taken when func is SIG_DFL)
for each signal.
These are discussed in detail below.
Exit
The receiving process is terminated abnormally
when it gets the signal,
with all the consequences outlined in
exit(S).
The status made available to the
wait( )
family of calls
indicates abnormal termination by the specified signal.
Core
Same as ``Exit'',
with the addition that a core file image of the process
is constructed according to
the system's rules for core file generation; see
core(FP)
Stop
The receiving process is stopped rather than terminated
when it gets the signal.
The distinction is that a stopped process can be
started again with a SIGCONT
whereas a terminated process cannot be restarted
under any circumstance.
Whenever a process receives a
SIGSTOP, SIGTSTP,
SIGTTIN, or SIGTTOU signal,
regardless of its disposition,
any pending SIGCONT signal is discarded.
A process stopped by
the above four signals is said to be in
a job control stop.
When the process stops,
a SIGCHLD may in turn be generated
to the process's parent;
see ``Child''.
No effect
The process continues executing,
or remains in a job control stop
if it was in one.
Continue
Continue the process.
The process resumes executing,
even if it was previously in a job control stop
and any pending job control stop signals
(SIGSTOP, SIGTSTP,
SIGTTIN, and SIGTTOU
are discarded.
When the process stops,
a SIGCHLD may in turn be generated
to the process's parent;
see ``Child''.
Child
For the SIGCHLD signal,
the meaning of the standard func values are:
SIG_DFL --ignore signal
The signal is to be ignored;
the process is continued.
If the signal was generated by the
exit(S)
of a child process,
that process remains as a ``zombie''
until the parent calls one of the
wait( )
system calls to read its termination status.
SIG_IGN --ignore signal
The signal is to be ignored
and the calling process's child processes
do not become zombie processes when they terminate.
See
exit(S).
function address --catch signal
In addition to the standard behaviors,
while the process is executing the signal handler,
any received SIGCHLD signals are ignored.
In addition, the
exit(S)
and
wait( )
family of system calls
are affected as follows:
wait family: wait, wait3, waitid, and waitpid
If the disposition of SIGCHLD
is set to SIG_IGN,
these calls block
until all of the calling process's child processes terminate;
They then return a value of -1
with errno set to ECHILD.
This does not apply to
waitid(S)
or
waitpid(S)
called with the WNOHANG flag.
exit
If the parent of an exiting process is ignoring SIGCHLD,
the exiting process does not become a zombie process.
In most cases,
the SIGCHLD signal is
only sent to notify a process of the termination of its children.
If the handler for the SIGCHLD signal
is established by
sigaction(S)
without the SA_NOCLDSTOP flag,
SIGCHLD is also sent
when the calling process's children
are stopped or continued due to job control.
When processing a pipeline,
the shell makes the last process in the pipeline
the parent of the preceding processes.
A process that may be piped into in this manner
(and thus become the parent of other processes)
should either not catch SIGCHLD
or be prepared to receive SIGCHLD signals
for children that it did not explicitly create.
Poll
The default action if SIGPOLL is requested
but not caught is to erminate abnormally
as for Exit.
SIGPOLL
is issued when a file descriptor corresponding
to a STREAMS
file or socket has a ``selectable'' event pending.
A process must specifically request that this signal be sent
using the I_SETSIGioctl call.
Otherwise, the process never receives SIGPOLL.
User-specified disposition of a signal
Use the
sigaction(S),
sigset(S),
or
signal(S)
system calls
to change the disposition for a signal
from SIG_DFL
to either SIG_IGN,
or an address of a function that is defined by the user
that is called a ``signal handler''.
SIG_DFL and SIG_IGN are macros,
defined in the <signal.h> file,
that expand to a constant expression
of type pointer to function returning void,
and having a unique value
that does not match a declarable function.
SIG_DFL -- execute default signal action
Upon receipt of the signal specified by sig,
the receiving process will
take the default action.
The default action for each signal is noted in the table below
with details in
the ``Default disposition of signals" section below.
SIG_IGN -- ignore signal
Upon receipt of the specified signal,
the signal is ignored.
The SIGKILL and SIGSTOP signals
cannot be ignored.
signal handler -- (user-defined signal-catching function)
The signal handler is a routine
that is coded as part of the application.
The address of this function is defined
as the func argument
to
sigaction(S),
sigset(S),
or
signal(S).
When the process receives the specified signal,
it executes the signal handler
pointed to by func.
The sig signal number
is passed as the only argument to the signal handler,
except for hardware-generated signals
which pass additional arguments.
Before entering the signal handler,
the value of func
for the caught signal may be set to SIG_DFL;
see the
``Lifetime of a signal disposition''
section below.
Upon return from the signal handler, the receiving process
resumes execution at the point it was interrupted.
If the disposition has been set with the
sigset( )
or
sigaction( )
function,
certain signals are automatically blocked
while the signal handle is executing,
and automatically unblocked when it returns:
If the disposition has been set with
sigset( ),
the signal that is being delivered is blocked.
If the disposition has been set with
sigaction( ),
the signal is blocked
unless the SA_NODEFER
or SA_RESETHAND flag was set in the
sigaction( )
call; the signals specified in the
sa_mask member of the sigaction structure
are also blocked.
If a
longjmp(S)
is used to leave the signal catcher,
then the signal must be explicitly
unblocked by the user; see
sigprocmask(S)
and
sigsetjmp(S).
The func function argument
is not checked for validity
when the dispostion is established by the
sigaction(S),
sigset(S),
or
signal(S)
calls.
Results are undefined
if the delivery of a signal causes
an attempt to execute a function at a bad address.
The signal handler is always passed the signal number;
this may be its only argument,
unless the disposition was set by the
sigaction(S)
function with the SA_SIGINFO flag.
The SA_SIGNIFO flag can be used
by the receiver of a signal
to request detailed notification
about the source and context of the signal
and why it was generated;
see
siginfo(FP)
and
ucontext(FP)
for more information.
When the signal handler returns, the receiving process
resumes execution at the point it was interrupted,
unless the signal handler makes other arrangements.
Lifetime of a signal disposition
During
fork(S),
the set of signal actions for a process
is initialized from that of its parent.
Typically, a process starts out
with all signals set to the default disposition
(SIG_DFL),
and with no signals masked.
This is only a typical default;
a robust application must be prepared
to be started with some or all of its signals
ignored and/or blocked.
During
exec(S),
signal dispositions of SIG_DFL
and SIG_IGN remain installed.
Signals whose dispositions specify handler functions
are reset to SIG_DFL.
The process's signal mask is unaffected by
exec(S).
During process execution,
signal dispositions of SIG_DFL and SIG_IGN
remain installed until explicitly changed.
Signal dispositions that specify
a signal handler (signal-catching function)
may remain installed,
or may be reset to SIG_DFL after being caught once,
depending on how they are installed:
Handlers installed by
sigaction(S)
without the SA_RESETHAND flag
or by
sigset(S)
remain installed.
Handlers installed by
sigaction(S)
with the SA_RESETHAND flag
or by
signal(S)
are reset to SIG_DFL before entry to the handler.
Handlers of the SIGILL,
SIGTRAP, and SIGPWR signals
are never automatically reset after being caught.
It is difficult or impossible
to reliably handle signals
when their dispositions are continually being reset;
for this reason,
signal(S)
is not appropriate for new applications.
Interruption of a system call by a signal
A signal handler can be called
while a process is waiting for
the completion of a system call.
This applies mainly to system calls
that can take a long time,
like
read(S)
and
write(S)
and other input/output operations.
These system calls can become blocked
while waiting for completion;
an example is a
read(S)
operation on an interactive terminal
that must wait for a human to deliberate and respond.
When a signal interrupts such a system call,
its handler is executed.
If the handler returns normally,
one of three things happens:
If the system call had already transferred
some, but not all, of the data,
it returns normally,
giving the true amount of data that was transferred
as its return value.
If the system call had not yet transferred any data,
its behavior depends on how the signal handler was installed.
If it was installed by
sigaction(S)
with the SA_RESTART flag,
the system call transparently restarts.
Otherwise, the interrupted system call
returns -1 with errno set to EINTR.
Applications that establish signal handlers
must always be prepared for I/O operations
to return partial read or write operations.
Unless the handlers are established by
sigaction(S)
with SA_RESTART,
the application must also be prepared
for returns of -1 with errno set to EINTR.
Summary of signal functions
SCO OpenServer supports traditional,
System V, and POSIX signal handling functionality.
The following lists summarizes the functions
according to their functionality: