public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [bug?]  strange behaviour with longjmp, itimer, and read/recv (but not pause)
@ 2005-01-20 21:47 Chris Friesen
  2005-01-20 21:53 ` Chris Friesen
  0 siblings, 1 reply; 3+ messages in thread
From: Chris Friesen @ 2005-01-20 21:47 UTC (permalink / raw)
  To: Linux Kernel Mailing List



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,


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [bug?]  strange behaviour with longjmp, itimer, and read/recv (but not pause)
  2005-01-20 21:47 [bug?] strange behaviour with longjmp, itimer, and read/recv (but not pause) Chris Friesen
@ 2005-01-20 21:53 ` Chris Friesen
  2005-01-20 22:09   ` [bug?] strange behaviour with longjmp, itimer, and read/recv (but not pause) -- solved Chris Friesen
  0 siblings, 1 reply; 3+ messages in thread
From: Chris Friesen @ 2005-01-20 21:53 UTC (permalink / raw)
  To: Linux Kernel Mailing List

Friesen, Christopher [CAR:VC21:EXCH] wrote:

> 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.

My bad, didn't notice that pause() doesn't get restarted.  So the 
setjmp/longjmp code isn't being called with pause.

Also, behaviour is the same with 2.6.5 on a P4.

Chris

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [bug?]  strange behaviour with longjmp, itimer, and read/recv (but not pause) -- solved
  2005-01-20 21:53 ` Chris Friesen
@ 2005-01-20 22:09   ` Chris Friesen
  0 siblings, 0 replies; 3+ messages in thread
From: Chris Friesen @ 2005-01-20 22:09 UTC (permalink / raw)
  To: Linux Kernel Mailing List

Bah...

As all of you no doubt suspected, I should have been using 
sigsetjmp()/siglongjmp().

Sorry to waste your time.

Chris

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2005-01-20 22:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-01-20 21:47 [bug?] strange behaviour with longjmp, itimer, and read/recv (but not pause) Chris Friesen
2005-01-20 21:53 ` Chris Friesen
2005-01-20 22:09   ` [bug?] strange behaviour with longjmp, itimer, and read/recv (but not pause) -- solved Chris Friesen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox