Date: Mon, 25 Jun 2001 02:25:08 -0400 (EDT) From: Daniel Eischen <eischen@vigrid.com> To: Valentin Nechayev <netch@iv.nn.kiev.ua> Cc: Louis-Philippe Gagnon <louisphilippe@macadamian.com>, freebsd-hackers@FreeBSD.ORG Subject: Re: pthread/longjmp/signal problem Message-ID: <Pine.SUN.3.91.1010625022147.6848A-100000@pcnet1.pcnet.com> In-Reply-To: <20010625090332.A416@iv.nn.kiev.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
On Mon, 25 Jun 2001, Valentin Nechayev wrote: > Thu, Jun 21, 2001 at 10:55:10, louisphilippe (Louis-Philippe Gagnon) wrote about "pthread/longjmp/signal problem": > > > 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. > > libc_r provides its own signal handling. sigaction() called by you > is libc_r function which replaces your handler with its own and record > your handler in its private data. On SIGSEGV, not your handler is called, > but libc_r's: > > 1370 lou CALL write(0x2,0xbfbff050,0xf) > 1370 lou GIO fd 2 wrote 15 bytes > "before sigsegv > " > 1370 lou RET write 15/0xf > 1370 lou PSIG SIGSEGV caught handler=0x28072444 mask=0x0 code=0x0 > 1370 lou CALL sigprocmask(0x3,0x2807f0d8,0) > 1370 lou RET sigprocmask 0 > 1370 lou CALL sigaltstack(0x28084aa0,0) > 1370 lou RET sigaltstack 0 > 1370 lou CALL write(0x2,0xbfbfecf0,0xb) > 1370 lou GIO fd 2 wrote 11 bytes > "in handler > " > 1370 lou RET write 11/0xb > 1370 lou CALL write(0x2,0xbfbff050,0x13) > 1370 lou GIO fd 2 wrote 19 bytes > "longjmp successful > " > > Your handler doesn't contain sigaltstack() call, does it? ;) > > With longjmp, you destruct libc_r's internals because it can't do > needed cleanups. This is suppose to work as long as you are jumping to the current threads stack. > > 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. > > You cannot do longjmp() out from signal handler with libc_r. You are suppose to be able to do this. I will look at it when I get the chance. > If you nevertheless want to implement your function, you should > > 1) Block all signals except SIGSERV via sigprocmask(); > especially block SIGVTALRM (libc_r on-timer switching signal) > 2) Call __sys_sigaction() instead of sigaction(), to call real syscall > and not libc_r wrapper. Don't forget to restore previous handler > with the same call after restoring. __sys_sigaction is only in current, -stable still has _thread_sys_sigaction. But you don't really want to know that -- it is suppose to work correctly. > 3) Really call test and handle return from signal handler. > 4) Restore kernel's sigaction and sigprocmask. > > And this way uses undocumented implementation details of libc_r > and can stop to work in any moment. > > > 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. > > linuxthreads uses another approach. But it also deals with signal handlers. -- Dan Eischen 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?Pine.SUN.3.91.1010625022147.6848A-100000>