SIGALRM can't be delivered after longjmp from handler?
David A. Gatwood
dgatwood at deepspace.mklinux.org
Thu Mar 16 12:57:11 EST 2000
On Wed, 15 Mar 2000, Peter M. Jansson wrote:
>
> I wrote the example that follows to illustrate what I think is a
> problem with signal delivery. If this program works, then it should run
> in 5 cycles; the first 2 end with the "Timed out" message, while the
> last 3 end with the "Wait interrupted" message. On my PowerMac 7200
> running 2.2.15pre3, I get 2 "Timed out" cycles, one "Wait interrupted"
> cycle, and then two more "Timed out" cycles. What I think is going on
> is that, once the SIGALRM handler executes the longjmp, no further
> SIGALRM signals are delivered to the process -- I don't know if this is
> because the signals aren't delivered, or because the setitimer call
> isn't working. I've observed this example to run correctly on BSD/OS,
> IRIX, and Solaris, and seen it fail on LinuxPPC and Linux x86.
Some OSes automatically reset signal handlers to SIG_DFL (which is SIG_IGN
for alarm) after they receive a signal and some leave the signal hndler in
place. The BSDs to the latter, and Linux, IIRC, does the former. You can
fix this by re-installing the handler during the signal handler function,
but the better way is to use sigaction instead of signal, which will give
consistent behaviour on all platforms.
Later,
David
> -------------------------------
>
> #include <signal.h>
> #include <setjmp.h>
> #include <sys/time.h>
> #include <stdio.h>
>
> static jmp_buf env;
> static unsigned int count = 0;
>
> static void
> interrupt()
> {
signal(SIGALRM, interrupt);
> printf ("Interrupt: %d\n", count);
> if (count > 2)
> longjmp(env, 1);
> }
>
> main ()
> {
> struct timeval tv;
> struct itimerval it, oit;
>
> while (count++ < 5) {
> printf("Cycle %d\n", count);
>
> if (setjmp(env)) {
> printf ("Wait interrupted\n");
> } else {
> if (signal(SIGALRM, interrupt) == SIG_ERR)
> perror("signal");
> getitimer(ITIMER_REAL, &oit);
> timerclear(&it.it_interval);
> it.it_value.tv_sec = 2;
> it.it_value.tv_usec = 16665;
> if (setitimer(ITIMER_REAL, &it, &oit) < 0)
> perror("tick");
> printf ("Set timer; waiting...\n");
> tv.tv_sec = 5;
> tv.tv_usec = 0;
> select(0, NULL, NULL, NULL, &tv);
> printf ("Timed out\n");
> }
> }
> }
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
More information about the Linuxppc-dev
mailing list