innfeed segfaults on NULL buffer in getBanner() - mine too..

Julien ÉLIE julien at trigofacile.com
Tue Aug 7 17:38:13 UTC 2007


En réponse à Russ Allbery :
> connectionDone is presumably what set up the buffers for the getBanner
> call.

Yes it is.


> It calls:
>
>      readBuffers = makeBufferArray (bufferTakeRef (cxn->respBuffer), NULL) ;
>      if ( !prepareRead (e, readBuffers, getBanner, cxn, 1) ) /* ... */
>
> so the buffers we're using should be coming from cxn->respBuffer.  Or,
> alternately, if it got a short read, it may be getBanner itself that set
> things up with a new buffer.

It is after this prepareRead that the end pointer is messed up (and not during
the prepareRead in getBanner itself).


> The behavior is consistent with bufferTakeRef returning NULL, which it
> will do if cxn->respBuffer is NULL.

It is not NULL at this point.

(gdb) print cxn->respBuffer
$14 = 0x56e048
(gdb) print *cxn->respBuffer
$15 = {refCount = 2, mem = 0x56d400 "", memSize = 256, dataSize = 0, deletable = true, bufferDeletedCbk = 0, bufferDeletedCbkData = 
0x0, next = 0x56e000,
  prev = 0x0}


> I think the only way to track down what's going on here is to walk through
> innfeed in gdb and set a lot of breakpoints and try to figure out where
> the buffer initialization is going wrong.

Just after readBuffers = makeBufferArray (bufferTakeRef (cxn->respBuffer), NULL),
we have:

(gdb) print readBuffers
$17 = (Buffer *) 0x56f800
(gdb) print *readBuffers
$18 = 0x56e048

It is in fact cxn->respBuffer.

Then we go into prepareRead.  It returns 1.
And the end pointer looks like:

(gdb) print *e
$24 = {inBuffer = 0x56f800, inBufferIdx = 0, inIndex = 0, inMinLen = 1, inAmtRead = 0, inCbk = 0x422820 <getBanner>, inClientData = 
0x56a600, outBuffer = 0x0,
  outBufferIdx = 0, outIndex = 0, outSize = 0, outAmtWritten = 0, outProgressCbk = 0, outDoneCbk = 0x4225e0 <connectionDone>, 
outClientData = 0x56a600,
  workCbk = 0, workData = 0x0, myFd = 6, myErrno = 0, selectHits = 0}

Then, initReadBlockedTimeout (cxn) and VALIDATE_CONNECTION (cxn) occur.
And we return in endpoint.c (line 810):
                  /* get it again as the write callback may have deleted the */
                  /* endpoint */
                  if (specialCheck)
[...]
And we finally arrive here in endpoint.c:

742                           if ((rval = doRead (ep)) != IoIncomplete)
(gdb)
744                               Buffer *buff = ep->inBuffer ;
(gdb)
746                               FD_CLR (fd, &rdSet) ;
(gdb)
749                               ep->inBuffer = NULL ;
(gdb)
751                               if (ep->inCbk != NULL)
(gdb)
752                                 (*ep->inCbk) (ep,rval,buff,ep->inClientData) ;
(gdb)

So the end pointer has a NULL inBuffer...

Breakpoint 2, getBanner (e=0x56a800, i=IoDone, b=0x56f800, d=0x56a600) at connection.c:1284
1284      Connection cxn = (Connection) d ;
(gdb) print *e
$28 = {inBuffer = 0x0, inBufferIdx = 0, inIndex = 0, inMinLen = 1, inAmtRead = 0, inCbk = 0x422820 <getBanner>, inClientData = 
0x56a600, outBuffer = 0x0,
  outBufferIdx = 0, outIndex = 0, outSize = 0, outAmtWritten = 0, outProgressCbk = 0, outDoneCbk = 0x4225e0 <connectionDone>, 
outClientData = 0x56a600,
  workCbk = 0, workData = 0x0, myFd = 6, myErrno = 0, selectHits = 1}
(gdb) step
1285      ASSERT (b[0] == cxn->respBuffer) ;
(gdb)
die (format=0x44f878 "assertion -- %s -- failed in file %s line %d") at messages.c:315
315         va_start(args, format);

-- 
Julien ÉLIE

« Dès l'époque secondaire, les mollusques construisaient leur coquille
  en suivant les leçons de géométrie transcendante. » (Gaston Bachelard) 



More information about the inn-workers mailing list