Programming Interfaces Guide

Signals and Process Group ID

For SIGURG and SIGIO, each socket has a process number and a process group ID. These values are initialized to zero, but can be redefined at a later time with the F_SETOWN fcntl(2) command, as in the previous example. A positive third argument to fcntl(2) sets the socket's process ID. A negative third argument to fcntl(2) sets the socket's process group ID. The only allowed recipient of SIGURG and SIGIO signals is the calling process. A similar fcntl(2), F_GETOWN, returns the process number of a socket.

You can also enable reception of SIGURG and SIGIO by using ioctl(2) to assign the socket to the user's process group.

/* oobdata is the out-of-band data handling routine */
sigset(SIGURG, oobdata);
int pid = -getpid();
if (ioctl(client, SIOCSPGRP, (char *) &pid) < 0) {
		perror("ioctl: SIOCSPGRP");
}

Another signal that is useful in server processes is SIGCHLD. This signal is delivered to a process when any child process changes state. Normally, servers use the signal to “reap” child processes that have exited without explicitly awaiting their termination or periodically polling for exit status. For example, the remote login server loop that was shown previously can be augmented, as shown in the following example.


Example 7–13 SIGCHLD Signal

int reaper();
...
sigset(SIGCHLD, reaper);
listen(f, 5);
while (1) {
		int g, len = sizeof from;
		g = accept(f, (struct sockaddr *) &from, &len);
		if (g < 0) {
			if (errno != EINTR)
				syslog(LOG_ERR, "rlogind: accept: %m");
			continue;
		}
		...
}
 
#include <wait.h>
 
reaper()
{
		int options;
		int error;
		siginfo_t info;
 
		options = WNOHANG | WEXITED;
		bzero((char *) &info, sizeof(info));
		error = waitid(P_ALL, 0, &info, options);
}

If the parent server process fails to reap its children, zombie processes result.