- 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