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