- From: Mikhail Grouchinski <mgrouch@usa.net>
- Date: 16 Mar 00 19:14:08 EST
- To: www-lib@w3.org
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