Signals and Sockets [ Berkeley Sockets/iX Reference Manual ] MPE/iX 5.0 Documentation
Berkeley Sockets/iX Reference Manual
Signals and Sockets
What is a Signal?
A signal is the notification to a process of an event. This event can be
either external or internal. A signal can be generated by either the
operating system or a process (even the same process that is receiving
it). Other than which signal is delivered, no information is delivered
with the signal. A process cannot determine what process generated the
signal, how it was generated or which file descriptor, if any, for the
process the signal is related to. When a signal is sent to a process and
the process is made aware of that signal, it is said that that signal has
been raised.
There are several methods for generating a signal. However, for the
purposes of this discussion, how signals are generated is largely
immaterial. Suffice it to say that most signals related to sockets are
generated by software conditions.
There are many system calls relating to the handling of signals. Please
refer to the POSIX manuals for a more complete description. For the
purposes of illustration, we will use the signal() system call, which is
the simplest of the system calls dealing with sockets, to describe signal
handling.
There are several default actions possible that may be performed upon
receipt of a signal. Some of them are: ignore the signal, terminate the
process, suspend (stop) the process, and resume (continue) the process.
Of the signals generated by sockets, only the ignore and terminate
defaults are available. Which of these actions is the default for signal
reception depends on the signal.
When signal() is called, there are three methods for handling the signal.
They are SIG_DFL, SIG_IGN or a user specified signal handler. SIG_DFL
sets the signal handler to the default signal handler. This is useful if
the signal handler was changed and the process should be returned to an
initial state. SIG_IGN sets the signal handler to ignore this signal.
The third choice can be the most useful. It is used to set up a user
specifiable function to be the signal handler. Whenever that signal is
raised, the user specified function is invoked. This is generally
referred to as catching a signal. A typical example of this type of
handler (for a signal that is not indicative of an error state) is to
either set or increment a flag indicating that a signal was received.
Sockets and Incoming Signals
When a signal is sent to a process while performing a sockets function,
several things may occur. This depends on whether the socket function is
defined as a slow function. A slow function is a function that can block
indefinitely. For sockets, these functions are read, write, recv, send,
recvfrom, recvmsg, sendmsg, and accept. All other sockets functions are
fast.
Fast functions are not interrupted by a signal. Instead, the signal is
raised when these socket functions exit.
Slow functions are interrupted by a signal if they are blocked waiting
for IO (if they are processing IO, they are not interrupted). They are
interrupted in the middle of processing by the raising of a signal. They
stop what processing they are doing and return the error EINTR. They do
not complete the IO that was initiated. The user program must
re-initiate any desired IO explicitly.
Signals Generated By Sockets
There are two signals that can be generated by actions on a socket. They
are SIGPIPE and SIGIO. A SIGPIPE is generated when a send operation is
attempted on a broken socket. One way of breaking a socket is to do a
shutdown(,2) on a socket. The default action is to terminate the
process. The target of the signal is the process attempting the send.
The other signal is SIGIO. SIGIO is somewhat more complex than SIGPIPE.
First, a call to ioctl() to request the enabling FIOASYNC is required to
enable generation of this signal. Second, another call to ioctl() is
required to request SIOCSPGRP, which sets the target process group. A
target process group is either a process (specified by a positive process
id) or a process group (specified by a negative process id). A SIGIO
signal is generated whenever new IO can complete on a socket. Examples
of when a SIGIO signal is generated are when new data arrives at the
socket, when data can again be sent on the socket, when the socket is
either partially or completely shutdown or when a listen socket has a
connection request posted on it.
Using Signals With Sockets
There are several issues to using sockets that can be resolved through
the use of signals. One is the fact that there are no timeouts on
sockets. A similar functionality can be accomplished with the use of the
SIGALRM signal and the alarm() system call. Alarm() sets up a SIGALRM
signal to be received a certain specified number of seconds in the
future. If the socket call is not completed by the time the alarm goes
off, it is interrupted. The alarm is reset by another call to alarm()
with a time of 0 seconds.
Another issue that may arise if the use of signals to indicate when IO
can complete. Use of the SIGIO signal can be used to indicate when IO
can complete. After enabling the SIGIO signal on all of the desired
descriptors, pause() is called to wait for a signal to arrive. Then,
either using a polling method or select(), it can be determined which
socket has IO ready to complete. This avoids repeated calls to
no-blocking IO when there is no IO present.
MPE/iX Specific
Due to POSIX/iX design considerations, the read() and write() system
calls may not be interrupted by a signal while they are running system
code (see the POSIX.1/iX Reference Manual).
Select() does not support signals in this release. Its non-support takes
the following form: when blocked in select(), any signal that arrives,
even those we are set to ignore, interrupts select() and causes it to
return EINTR. Even ordinary signals that default to ignore, such as
SIGCHLD (the signal generated when a child process terminates), cause
select() to be interrupted. Care must be taken to account for this
non-support.
The SIGURG signal is not supported in this release. This is the signal
that is sent when urgent data is received on a socket.
None of the socket functions should be called from within a signal
handler.
MPE/iX 5.0 Documentation