SETL programs can ``read'' high-priority signals from other processes, from the kernel, and from periodic timers. The I/O system is also used to specify signals that are to be ignored, meaning in most cases relieved of the duty of terminating the process.
Routing signals and timer alarms through the I/O system, and making their associated streams candidates for multiplexed event-sensing through the select routine described in Section 2.5 [Multiplexing with Select], are of great value in helping to create small, modular processes that are simultaneously responsive to I/O events, signals, and the passage of time.
A SETL program arranges to receive signals of a given type by opening a stream on the signal name, such as INT, HUP, or TERM, contained case-insensitively in a string such as `INT', `HUP', or `TERM' respectively, or even `SIGINT', `SIGHUP', or `SIGTERM'. The full list of signal names supported by a given Posix-compliant Unix system can be obtained from the kill command through its ``list'' parameter (a lowercase L):
kill -lDescriptions of the signals can usually be found on Unix systems in the customary way, i.e., through a command like man signal, and further details are often available in the C ``header'' files, normally under the directory /usr/include. Section 2.8 [Processes and Process Groups] shows how to send signals; the present section is about how to receive and process them.
To start intercepting signals, a SETL program executes *
fd := open (signal_name, `signal'); -- or `signal-in'For example, signal_name might contain `HUP' or `SigHup', in which case subsequent HUP signals sent to the SETL process will be caught and presented to the SETL program as lines of input on fd, one signal per line. When the SETL program detects that a signal of this type has been sent to it (this detection will often be through the select routine discussed in Section 2.5 [Multiplexing with Select]), it should explicitly receive the signal by reading a line from the stream's file descriptor, e.g., *
line := getline fd;At the time of this writing, the resulting line is specified only to contain at least the null string, but for some signal types, collateral information may eventually prove useful. To remain upwardly compatible, therefore, SETL programs should read whole lines from signal streams.
A signal type may have any number of streams open over it, and a line will be delivered to all of them whenever a signal of that type is caught.
If a particular type of signal is not being caught, because no streams are open over it, signals of that type may still be stripped of their default effect on the SETL process (which for many is to terminate the process) by being explicitly ignored: *
fd := open (signal_name, `ignore'); -- or `ignore-signal'The only meaningful thing that can be done with the fd returned in this case is to close it. When the last ignoring stream on the given signal type is closed, the default behavior of the signal type is restored unless there are by then signal-receiving streams open on that type. If there are both receiving and ignoring streams open on a given signal type, the receivers take precedence--incoming signals will be delivered rather than being ignored.
A SETL program may open any number of recurring interval timer streams based on ``wall-clock'' time, user-mode CPU time, or total CPU time: *
fd := open (ms, `real-ms'); -- wall-clock timeThe ms argument in each of these timer cases is actually a string consisting of decimal digits to be interpreted as the number of milliseconds that is supposed to elapse between each time a new line becomes available on that stream. These timer I/O modes make implicit use of the signals ALRM, VTALRM, and PROF respectively.
fd := open (ms, `virtual-ms'); -- user-mode CPU time
fd := open (ms, `profile-ms'); -- total CPU time
The file descriptors returned by open for signal and timer streams are ``pseudo-fd's'' in that they have no existence at the Unix level. This decision to to route signals and timers through the SETL I/O system was made primarily so that select (Section 2.5 [Multiplexing with Select]) can sense timing and other signals simultaneously with regular I/O events.