From: acourtny@unix1.tcd.ie (Antony A. Courtney)
Subject: reliable signals under BSD / SVR4
Summary: looks like they're not reliable
Keywords: signals, reliable, software interrupts
Organization: Trinity College, Dublin
Date: Mon, 31 Aug 1992 12:14:27 GMT

I wrote the following short program to test whether or not signals are reliable
on our particular SVR4 implementation  (A Siemens-Nixdorf RM600 running Sinix).

The particular implementation of signal() is from Stevens' "Advanced Programming
in the UNIX environment".  

The program simply installs a signal handler for SIGUSR1, fork()s, and the
parent sends 20 SIGUSR1 signals to the child as fast as it can.  The child
has a busy loop in the signal handler to make it deliberately slow.  The result
is that I only catch a random subset of the signals posted (sometimes I don't
catch any, other times I get 2 or 3).  I get similar behavior under 4.3BSD if
I use BSD's implementation of signal(), which is supposedly "reliable".

What's the word?  Are signals "reliable" or aren't they?

I admit I haven't read *every* single standard written about all the various
implementations and semantics of signals; that would probably take more time
than writing a reliable signal implementation!

Code follows, thanks for any help...

	-antony

------snip, snip----
/*
 * Program to test whether or not signals get queued.
 *
 * Antony A. Courtney, 21/2/92
 *
 */

#include <stdio.h>
#include <signal.h>

typedef void Sigfunc(int);

void handle_sig(int);

/* reliable version of signal, using POSIX sigaction */
Sigfunc *signal(int signo,Sigfunc *func)
{
	struct sigaction act,oact;

	printf("in signal()\n");
	act.sa_handler=func;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	if (signo==SIGALRM) {
#ifdef SA_INTERRUPT
		act.sa_flags |= SA_INTERRUPT;
#endif
	} else {
#ifdef SA_RESTART
		act.sa_flags |= SA_RESTART;
#endif
	}
	if (sigaction(signo, &act, &oact) < 0) {
		return (SIG_ERR);
	}
	return (oact.sa_handler);
}

main()
{
        int i,pid;

        /* install the signal handler here so that the child catches all
         * signals immediately.
         */
        if (signal(SIGUSR1,handle_sig)==SIG_ERR) {
                perror("signal");
                exit(1);
        }
        pid=fork();
        switch (pid) {
                case -1:
                        perror("fork");
                        exit(1);
                        break;
                case 0: /* child */
                        while (1) {
                                pause();
                        }
                        break;
                default: /* parent */
                        for (i=0; i < 20; i++) {
                                if (kill(pid,SIGUSR1) < 0) {
                                        perror("kill");
                                        exit(1);
                                }
                        }
                        wait(0);
                        break;
        }
}

void handle_sig(int x)
{
        static int count=0;
	int a,j;

        count++;
        printf("Got signal # %d\n",count);
	for (j=0; j < 100000; j++) {
		a=j;
	}
	printf("returning from signal handler\n");
}

---- snip, snip -----
--
********************************************************************************
* Antony A. Courtney                              Email: acourtny@unix1.tcd.ie *
* Computer Science Department                            antony@george.lbl.gov *
* Trinity College, Dublin, Ireland                Phone: 01+353+1-607389       *
Newsgroups: comp.unix.wizards