Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Jun 2001 10:55:10 -0400
From:      "Louis-Philippe Gagnon" <louisphilippe@macadamian.com>
To:        <freebsd-hackers@FreeBSD.ORG>
Subject:   pthread/longjmp/signal problem
Message-ID:  <0db001c0fa62$2b567800$2964a8c0@macadamian.com>

next in thread | raw e-mail | index | archive | help
No reactions the first time, let's try again.

I've encountered a problem in the interaction betwen signals, longjmp and
pthreads; I'm hoping someone can help me make sense of it.

I've been trying to implement a IsBadReadPtr-style function in FreeBSD by
using signal handlers and longjmp/setjmp. It seemed to work as expected,
until I started using the -pthread option to gcc (thus linking against
libc_r). Now the function only works on the first call; subsequent calls
hang on the segmentation fault.

Here's an example of the kind of code that causes problems :

#include <signal.h>
#include <setjmp.h>
#include <stdio.h>

sigjmp_buf env;

void handler(int n, siginfo_t *si, void *c)
{
 int z;
 fprintf(stderr,"in handler\n");
 siglongjmp(env, 1);
}

int main()
{
 int *x=0;
 int y=0;
 int z;
 struct sigaction act;

 act.sa_handler=NULL;
 act.sa_sigaction=handler;
 sigemptyset(&act.sa_mask);
 act.sa_flags=SA_SIGINFO;
 sigaction(SIGSEGV,&act,NULL);

 if(sigsetjmp(env,1))
  fprintf(stderr,"longjmp successful\n");

 if(y>=10)
  return 0;
 y++;

 fprintf(stderr, "before sigsegv\n");
 z=*x;

 return 1;
}

Basically, the app registers a signal handler for SIGSEGV, initializes a
setjmp() buffer, then provokes a segmentation fault. The expected behavior
is for the signal handler to get called, which will longjmp() bask to main,
where another segmentation fault will occur, which repeats the process.
After 10 times, the if(y>=10) condition makes the program exit.

Compiling with 'gcc test.c', the program behaves as expected. But if I
compile with 'gcc -pthread test.c', the signal handler gets called a single
time and longjmp()s back into main; the program then hangs on the second
segmentation fault. 'top' shows the process is eating up all available CPU.
Using gdb, trying to continue execution with 'stepi' after receiving the
second SIGSEGV immediately returns control to gdb with another SIGSEGV, then
another, and so on.

If I use sigsetjmp(env,0) (instead of 1, so the signal mask isn't restored
by longjmp), I get this hang even without -pthread, which leads me to think
that libc_r blocks the signal even when it shouldn't.

I tried :
-Unblocking the signal manually (with sigprocmask and pthread_sigmask)
-Replacing sigsetjmp/siglongjmp by setjmp/longjmp
-Calling setjmp() before sigaction instead of after
-Using a ANSI-style handler instead of POSIX (int handler(int code))
-Using the flags SA_ONSTACK, SA_NODEFER
-Using sigaltstack
-... and various combinations of these

none of this made any difference.

Doing some research in previous bug reports, this seems very similar to bug
14685 (setjmp/longjmp in threaded app cause subsequent read to run forever),
but that bug has been closed for over a year... I couldn't find any other
really similar bug reports (though 22286 and 21943 seemed vaguely related)

Out of curiosity, I tried installing the linuxthreads port and using that :
this actually works, but I may not be able to use it as a permanent
solution.

My system is FreeBSD 4.3-RELEASE, with all binaries straight off the CD
(nothing rebuilt); installed on a single-processor PIII-600
I tried the same test on a FreeBSD 4.2 machine : same results. I tried
rebuilding libc and libc_r on that machine : no change (though I didn't
expect any)
I also tried the same code in Linux (RedHat 6.1), where it behaves as
expected.

So the questions are :
-Am I doing something obviously wrong?
-Is this a bug?
-Is this a known bug with a known workaround?

Thanks for any help.

Louis-Philippe Gagnon


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?0db001c0fa62$2b567800$2964a8c0>