signals and sockets

Jacob Gladish jake@gladish.info
Fri Aug 6 17:33:00 GMT 2004



> -----Original Message-----
> From: java-owner@gcc.gnu.org [mailto:java-owner@gcc.gnu.org] On Behalf
Of
> Gladish, Jacob
> Sent: Thursday, August 05, 2004 5:39 PM
> To: java@gcc.gnu.org
> Subject: FW: signals and sockets
> 
> 
> 
> >
> > syslog() has a critical section in which it does all the
> > messing with signals.  libc doesn't stash the user sigaction
> > in a per thread
> > variable: it's just an array __sighandler[signo].
> >
> > It seems from your stack trace that __sighandler[13] is set
> > to 0x00000003.  A GDB watchpoint on that memory can tell you
> > how that happens.
> >
> > Andrew.
> >
> 
> I saw the same thing and was wondering myself how that could possibly
be
> set to 3. I still have no clue.



A colleague of mine pointed out this piece of code in i386-signal.h

#define MAKE_THROW_FRAME(_exception)
\
do
\
{
\
  void **_p = (void **)&_dummy;
\
  struct sigcontext_struct *_regs = (struct sigcontext_struct *)++_p;
\
 
\
  /* Advance the program counter so that it is after the start of the
\
     instruction:  the x86 exception handler expects
\
     the PC to point to the instruction after a call. */
\
  _regs->eip += 2;
\
 
\
}
\
while (0)

We've been able to reproduce this with a unit test, and believe that the
problem is indeed the use of syslog. If the call to syslog is in
progress, and the SIG_PIPE is delivered and the race occurs where the
sighandler may try to call a function pointing to one, a segv occurs and
then the code jumps to the java segv handler. The code then increments
the eip by 2 making it look like the segv was acutally on a 3 address
when it was really on 1. I think this is most certainly a problem with
our code and not a defect in gcj, but considering that java is
inherently a multithreaded environment, the use of signal handling
should be used only when no other solution is practical. I think
changing the writes to sends in the socket code would help prevent
situations like this. I have made this change to our environment in
natPlainSocketImpl.cc because syslog is pretty useful and I can't think
of any other way to work around this.


560c560,563
<       r = _Jv_write (fnum, &d, 1);
---
>
>       // To avoid using a sigaction to ignore pipes, we'll use send.
>         // r = _Jv_write (fnum, &d, 1);
>       r = send( fnum, &d, 1, MSG_NOSIGNAL );
598c601,604
<       int r = _Jv_write (fnum, bytes, len);
---
>
>       // To avoid using a sigaction to ignore pipes, we'll use send.
>         // int r = _Jv_write (fnum, bytes, len);
>       int r = send( fnum, bytes, len, MSG_NOSIGNAL );


-jake




> 
> I did discover that you cannot use syslog with the gcj java runtime.
If
> you do, then a race condition exists with the syslog. It's possible
that
> a sighandler with address "1" (SIG_IGN) might get called because of
the
> temporary installation of the syslog's sighandler and the restoration.
> The check to see if a sighandler is installed caould pass while syslog
> has it's handler installed, then restores it to the SIG_IGN, before
the
> actual call, which would result in a call to a sighandler with address
> 1.
> 
> -jake




More information about the Java mailing list