I'm seeing something odd, and I'm hoping someone can help. Running linux 2.6.9 on ppc.

I was writing a small test program to verify behaviour of network code when interrupted by a signal. To make the code bulletproof (or so I hoped) I used setjmp/longjmp to recover from the case where the syscall was being automatically restarted. Everything seemed to be okay.

However, I then reversed the order of the tests (doing the SA_RESTART case first). At this point I got the strange behaviour that the third signal was never delivered. Strace and gdb both show the recv() call running forever, and the signal never gets delivered.

It this point I suspected my setjmp/longjmp code was bad, so to test it I changed the recv() call to a pause() call. After that change, everything worked fine. I changed it to a read() call, and it breaks again with the third signal never being delivered.

Looking at the strace output, the only interesting thing I see is that both recv() and read() return with (errno == ERESTARTSYS), while pause() returns with (errno == ERESTARTNOHAND).

I've included the source code as well as traces of the pause() and recv() runs. If anyone has any ideas I'd love to hear them....

Chris









#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <linux/stddef.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <setjmp.h>
#include <unistd.h>

jmp_buf env;
volatile int signalled;
void handler(int sig)
{
        if (signalled)
                longjmp(env, 1);
        signalled = 1;
        struct itimerval itv = {{0,0},{0,500000}};
        setitimer(ITIMER_REAL,&itv,0);
}


void dotest(int sock, int flags) { int rc = setjmp(env); if (rc) { printf("system call was not interrupted\n"); return; } struct sigaction action; action.sa_handler = handler; action.sa_flags = flags; sigaction(SIGALRM, &action, 0); signalled = 0; struct itimerval itv = {{0,0},{0,500000}}; setitimer(ITIMER_REAL,&itv,0); char buf; rc = recv(sock, &buf, 1, 0); if(rc < 0) { int localerrno = errno; printf("recv() interrupted, errno: %d\n", localerrno); return; } }


int main()
{
int sock = socket (PF_INET, SOCK_DGRAM, 0);

printf("\ntesting behaviour of recv() on signal interruption with restarted syscalls:\n");
dotest(sock, SA_RESTART);


printf("testing behaviour of recv() on signal interruption with non-restarted syscalls:\n");
dotest(sock, 0);


        
   return 0;
}







using pause()


write(1, "testing behaviour of recv() on s"..., 76testing behaviour of recv() on signal interruption with restarted syscalls:
) = 76
rt_sigaction(SIGALRM, {0x10000844, [], SA_RESTART}, NULL, 8) = 0
setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={0, 500000}}, NULL) = 0
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={0, 500000}}, NULL) = 0
sigreturn() = ? (mask now [])
write(1, "recv() interrupted, errno: 4\n", 29recv() interrupted, errno: 4
) = 29
write(1, "testing behaviour of recv() on s"..., 80testing behaviour of recv() on signal interruption with non-restarted syscalls:
) = 80
rt_sigaction(SIGALRM, {0x10000844, [], 0}, NULL, 8) = 0
setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={0, 500000}}, NULL) = 0
pause() = ? ERESTARTNOHAND (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={0, 500000}}, NULL) = 0
sigreturn() = ? (mask now [])
write(1, "recv() interrupted, errno: 4\n", 29recv() interrupted, errno: 4
) = 29




using recv()



write(1, "testing behaviour of recv() on s"..., 76testing behaviour of recv() on signal interruption with restarted syscalls:
) = 76
rt_sigaction(SIGALRM, {0x100008a4, [], SA_RESTART}, NULL, 8) = 0
setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={0, 500000}}, NULL) = 0
recv(3, 0x7ffff620, 1, 0) = ? ERESTARTSYS (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={0, 500000}}, NULL) = 0
sigreturn() = ? (mask now [])
recv(3, 0x7ffff620, 1, 0) = ? ERESTARTSYS (To be restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
write(1, "system call was not interrupted\n", 32system call was not interrupted
) = 32
write(1, "testing behaviour of recv() on s"..., 80testing behaviour of recv() on signal interruption with non-restarted syscalls:
) = 80
rt_sigaction(SIGALRM, {0x100008a4, [], 0}, NULL, 8) = 0
setitimer(ITIMER_REAL, {it_interval={0, 0}, it_value={0, 500000}}, NULL) = 0
recv(3,


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to