libwww pipelining bug?

It seems the problems with pipelining in libwww (sometimes requests to
the same host get stuck in libwww) relate to incorrect handling
EPIPE, ECONNRESET in HTWriter_write.

I noticed significant difference in HTWriter and HTReader for handling
EPIPE, and ECONNRESET.

Here is a piece from HTReader_read

#ifdef EPIPE
  } else if (socerrno == EPIPE) {
      HTTRACE(STREAM_TRACE, "Read Socket. got EPIPE\n" _ soc);
      goto socketClosed;
#endif /* EPIPE */
#ifdef ECONNRESET
  } else if (socerrno == ECONNRESET) {
      HTTRACE(STREAM_TRACE, "Read Socket. got ECONNRESET\n" _ soc);
      goto socketClosed;
#endif /* ECONNRESET */
  } else {         /* We have a real error */

      if (request)
   HTRequest_addSystemError(request, ERR_FATAL, socerrno,
       NO, "NETREAD");
      return HT_ERROR;
  }
     } else if (!me->b_read) {

     socketClosed:
  HTTRACE(STREAM_TRACE, "Read Socket. FIN received on socket %d\n" _ soc);
  HTHost_unregister(host, net, HTEvent_READ);
  HTHost_register(host, net, HTEvent_CLOSE);
  return HT_CLOSED;
     }

Here is a piece from HTWriter_write

     } else {
#ifdef EPIPE
  if (socerrno == EPIPE)
      HTTRACE(STREAM_TRACE, "Write Socket got EPIPE\n");
#endif /* EPIPE */
  host->broken_pipe = YES;
  HTRequest_addSystemError(net->request, ERR_FATAL, socerrno, NO,
      "NETWRITE");
  return HT_ERROR;
     }
 }

Shouldn't it be something like that:

#ifdef EPIPE
  } else if (socerrno == EPIPE) {
      HTTRACE(STREAM_TRACE, "Write Socket %d got EPIPE\n" _ soc);
      goto socketClosed;
#endif /* EPIPE */
#ifdef ECONNRESET
  } else if (socerrno == ECONNRESET) {
      HTTRACE(STREAM_TRACE, "Write Socket %d got ECONNRESET\n" _ soc);
      goto socketClosed;
#endif /* ECONNRESET */
  } else {         /* We have a real error */

      if (request)
   HTRequest_addSystemError(net->request, ERR_FATAL, socerrno,
       NO, "NETWRITE");
      return HT_ERROR;
  }
     } 

...

 {
     socketClosed:
  HTTRACE(STREAM_TRACE, "Write Socket FIN received on socket %d\n" _ soc);
  HTHost_unregister(host, net, HTEvent_WRITE);
  HTHost_register(host, net, HTEvent_CLOSE);
  return HT_CLOSED;
     }

Here is a log

HTTP........ Generating HTTP/1.x Request Headers
HTTP........ Generating General Headers
Buffer...... Flushing 4003b2a0
Write Socket got EPIPE
Error....... Add  73 Severity: 1 Parameter: `Broken pipe' Where: `NETWRITE'
Host recover 4002b790 recovered 1 times. Moving 26 Net objects from pipe line
to pending queue
Timer....... Deleted active timer 40043550
Event....... No more events registered for socket 8
Event....... Reset MaxSock from 8 to 7
Event....... Socket 8 unregistered for HTEvent_READ
Event....... Couldn't find socket 8. Can't unregister type HTEvent_WRITE
Host recover Resetting net object 400433c8
HTTP Clean.. Called with status -904, net 400433c8
HTTPGen..... ABORTING...
HTTPRequest. ABORTING...
Buffer...... ABORTING...
FileWriter.. ABORTING...
Host recover Resetting net object 40048758

I also attach Olga's previous reply

Is that the requests are not failing but hanging unhandled in pipeline?
Trace may help. I used the plocking sockets and in some cases if one request
fails then all the subsequent requests to the same host would fail. I
(partially) fixed the problem returning HT_CLOSED instead of HT_ERROR from
HTWriter_write on broken pipe error. Also if you can stop in debugger in
HTWriter_write at the line where broken pipe is handled and look at the stack
- you can see that several functions do not check the return value of
HTWriter_write and just continue (to write on closed socket). That happens in
HTTPReq.c an d HTTPGen.c. In most cases the HT_CLOSED return will be
eventually
checked in consecutive writes (and HTHost_recoverPipe be called later) but
not
in all.

All that maybe does not have anything in common with your problem, but who
knows :-) ...

Olga. 



____________________________________________________________________
Get free email and a permanent address at http://www.netaddress.com/?N=1

Received on Thursday, 16 March 2000 19:14:21 UTC