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.

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

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


/netch

To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message

Reply via email to