From: Peter M. Jansson <hidden> Date: 2000-03-15 18:41:29
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.
Anyone seen this, and possibly know of a fix or workaround?
Pete.
-------------------------------
#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()
{
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/
From: Peter M. Jansson <hidden> Date: 2000-03-16 01:55:52
I made this exact change, and the program's behavior is unchanged. Did
you compile and run the program with your change and observe different
behavior? I still get only one "Wait interrupted" instead of three.
The signal is being delivered multiple times, it just isn't delivered
anymore after the longjmp, so I'm not sure that resetting the signal
handler is involved in this problem.
Pete.
On Wed, 15 Mar 2000, David A. Gatwood wrote:
From: David A. Gatwood <hidden> Date: 2000-03-16 01:57:11
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
From: David A. Gatwood <hidden> Date: 2000-03-16 02:10:44
On Wed, 15 Mar 2000, Peter M. Jansson wrote:
I made this exact change, and the program's behavior is unchanged. Did
you compile and run the program with your change and observe different
behavior? I still get only one "Wait interrupted" instead of three.
The signal is being delivered multiple times, it just isn't delivered
anymore after the longjmp, so I'm not sure that resetting the signal
handler is involved in this problem.
*ponders*.... Try sigsetjmp and siglongjmp
David
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
From: Peter M. Jansson <hidden> Date: 2000-03-16 02:18:33
OK...I just tried this with setting the second parameter of sigsetjmp to
1, instead of leaving it at 0. I need to RTFM more to understand why it
made a difference, but at least it works.
Thanks all!
Pete.
On Wed, 15 Mar 2000, David A. Gatwood wrote:
From: David A. Gatwood <hidden> Date: 2000-03-16 02:25:55
On Wed, 15 Mar 2000, Peter M. Jansson wrote:
Did that; no effect.
Well, it did for me, but I had to change the location of the signal()
line. The installation of the signal handler has to occur before the
sigsetjmp or else the longjmp() restores an empty set of handlers.
1. Move the if (signal(...)) line to right after the printf("Cycle...")
line
2. Change setjmp(jmp_buf) to sigsetjmp(jmp_buf,1)
3. Change longjmp to siglongjmp
4. add a signal(...) line to the beginning of the signal handler
The program then works as it did on *BSD.
David
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/