All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chris Friesen <cfriesen@nortelnetworks.com>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: [bug?]  strange behaviour with longjmp, itimer, and read/recv (but not pause)
Date: Thu, 20 Jan 2005 15:47:13 -0600	[thread overview]
Message-ID: <41F026E1.5050006@nortelnetworks.com> (raw)



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,


             reply	other threads:[~2005-01-20 21:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-20 21:47 Chris Friesen [this message]
2005-01-20 21:53 ` [bug?] strange behaviour with longjmp, itimer, and read/recv (but not pause) Chris Friesen
2005-01-20 22:09   ` [bug?] strange behaviour with longjmp, itimer, and read/recv (but not pause) -- solved Chris Friesen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=41F026E1.5050006@nortelnetworks.com \
    --to=cfriesen@nortelnetworks.com \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.