- From: Richard Atterer <richard@list03.atterer.net>
- Date: Mon, 3 Mar 2003 19:50:36 +0100
- To: www-lib@w3.org
Hello, here is the patch of the day... I believe that HTHost_killPipe() does not behave correctly - it (or rather the private function killPipeline() called by it) should close the HTTP/1.1 pipelined connection. Most of the time, the fact that it doesn't close it is not a problem, because when the event object of the connection next receives some data, it notices that nobody is listening to it, and its correct reaction is to close the connection: Host Event.. host 0x82998b0 `localhost' closed connection. Host Event.. Host 0x82998b0 `localhost' had 255 extraneous bytes: `...' Host Event.. Host 0x82998b0 `localhost' had 255 extraneous bytes: `...' ... Host Event.. Host 0x82998b0 `localhost' had 255 extraneous bytes: `...' Host Event.. Host 0x82998b0 `localhost' had 255 extraneous bytes: `...' Host Event.. Host 0x82998b0 `localhost' had 202 extraneous bytes: `...' Channel..... Delete 0x8284290 with semaphore 0, status 0 Channel..... Delete input stream 0x82b7e40 from channel 0x8284290 Channel..... Delete input stream 0x82b7e40 from channel 0x8284290 Socket read. FREEING.... Socket write FREEING.... Net Manager. Decreasing active sockets to 0, 1 persistent sockets Channel..... Deleted 0x8284290, socket 9 Net Manager. 0 active sockets, decreasing persistent sockets to 0 Host info... removed host 0x82998b0 as persistent Timer....... Dispatch timer 0x81f8870 Timer....... Deleted expired timer 0x81f8870 Host Event.. host 0x82998b0 `localhost' closed connection. However, things break in the following case: - We call HTHost_killPipe() while the pipeline is active, in the middle of a download - The requests of the pipeline are removed from the queue, but the connection is still open - Instead of executing the main loop, we *immediately* start another request for the same host. - Because the connection is still up, the request is added to the pipeline and the HTTP request headers are sent off - The new request's event object now "listens" to the connection - Instead of the HTTP reply headers it expects, it only gets what it thinks is "garbage" - in fact, it is the remaining data of the request which was aborted by HTHost_killPipe() earlier - libwww concludes that "this is a HTTP 0.9 or earlier host" and aborts the new request with an error :-( The libwww log output for this case is appended at the end of this mail. If you don't want to hack libwww, a fix for this problem is always to make the following calls yourself after calling HTHost_killPipe(): HTChannel_setSemaphore(host->channel, 0); HTHost_clearChannel(host, HT_INTERRUPTED); However, the nicer fix IMHO is the patch below, which closes the connection inside killPipeline(), but only if the pipeline isn't idle, i.e. it contains 1 or more requests. Cheers, Richard -- __ _ |_) /| Richard Atterer | CS student at the Technische | GnuPG key: | \/¯| http://atterer.net | Universität München, Germany | 0x888354F7 ¯ '` ¯ --- libwww-HTHost.c.orig 2003-02-17 23:43:12.000000000 +0100 +++ HTHost.c 2003-03-03 19:03:01.000000000 +0100 @@ -140,6 +140,10 @@ (*net->event.cbf)(HTChannel_socket(host->channel), net->event.param, type); } } + /* Close the connection, to prevent the server from sending us + the remainder of the data for the currently active request. */ + HTChannel_setSemaphore(host->channel, 0); + HTHost_clearChannel(host, HT_INTERRUPTED); } return YES; } ---------------------------------------------------------------------- The bug in action: Because the user clicked on "reload", my application calls HTHost_killPipe() to abort the current request. Host kill... Pipeline due to HTEvent_CLOSE event Host kill... Terminating net object 0x8259ed0 from pipe line Error....... Add 59 Severity: 1 Parameter: `Unspecified' Where: `HTLoadHTTP' HTTP Clean.. Called with status -902, net 0x8259ed0 Alert 64 for http://localhost/test obj 0x829abf4 HTTPGen..... ABORTING... HTTPRequest. ABORTING... Buffer...... ABORTING... FileWriter.. ABORTING... Net Object.. Delete 0x8259ed0 and call AFTER filters Host info... Remove 0x8259ed0 from pipe NB: The socket is kept open because it's a persistent HTTP/1.1 connection. Host Object. keeping persistent socket 9 Channel..... Delete 0x81f8918 with semaphore 1, status -902 Channel..... Delete input stream 0x82a8818 from channel 0x81f8918 MIME........ ABORTING... HTTPStatus.. ABORTING... FileWriter.. ABORTING... Channel..... Delete input stream 0x82a8818 from channel 0x81f8918 Buffer...... ABORTING... Channel..... Semaphore decreased to 0 for channel 0x81f8918 Timer....... Created one shot timer 0x81f8818 with callback 0x806d164, context 0x82a67a0, and relative timeout 60000 Host........ Object 0x82a67a0 going idle... Net Object.. Check for pending Net objects Net Object.. Freeing object 0x8259ed0 Net After... calling 0x8068e46 (request 0x8259bf8, response 0x827ceb0, status -902, context (nil)) Net After... calling 0x80679b2 (request 0x8259bf8, response 0x827ceb0, status -902, context (nil)) Request..... Delete 0x8259bf8 Request..... Deleting dangling output stream Response.... Delete 0x827ceb0 HTNet_killPipe() returns, and immediately I start a new request for the same host: Request..... Created 0x82b4ec8 HTSimplify.. `http://localhost/test' into ............ `http://localhost/test' Net Before.. calling 0x8068dc4 (request 0x82b4ec8, context (nil)) Auth Engine. Looking up `http://localhost/test' URL Tree.... did NOT find `w3c-AA' Auth Engine. No information Net Before.. calling 0x8068cca (request 0x82b4ec8, context (nil)) Net Object.. 0x8259ed0 created with hash 1 Net Object.. starting request 0x82b4ec8 (retry=1) with net object 0x8259ed0 HTTP........ Looking for `http://localhost/test' HTHost parse Looking up `localhost' on port 8000 Waah, it's going to reuse the connection: Host info... REUSING CHANNEL 0x81f8918 Host info... Added Net 0x8259ed0 (request 0x82b4ec8) to pipe on Host 0x82a67a0, 2 requests made, 1 requests in pipe, 0 pending Timer....... Deleted active timer 0x81f8818 HTHost...... No ActivateRequest callback handler registered Channel..... Semaphore increased to 1 for channel 0x81f8918 Host connect Unlocking Host 0x82a67a0 StreamStack. Constructing stream stack for text/x-http to */* Tee......... Created stream 0x81f8818 with resolver 0x404f0e90 HTTP........ Dumping response to `w3chttp.out' Tee......... Created stream 0x825a100 with resolver 0x404f0e90 HTTP........ Dumping request to `w3chttp.out' HTTP........ Generating HTTP/1.x Request Headers HTTP........ Generating General Headers Buffer...... Flushing 0x829ad00 Write Socket 196 bytes written to 9 Alert 16 for http://localhost/test obj 0x829abf4 Read Socket. WOULD BLOCK fd 9 glibwww_io_func: event 0x82a6860, event->cbf 0x806d19e Host Event.. READ passed to `http://localhost/test' Read Socket. 25601 bytes read from socket 9 Response.... Created 0x827d828 Garbage is received: Error....... Add 62 Severity: 8 Parameter: `993àBu$Þ±)oUuçüå@sRIWAË<2º]êFm©ºS)&Ò¤/AyØäö°PRÀìÛjµlôph@éÐ_ ,³DÀ¤7åÎÄÚ¼ÎÓÆ+ÁÝ£' Where: `HTTPStatusStream' StreamStack. Constructing stream stack for www/unknown to */* Host........ passing 100 bytes as consumed to 0x82a8818 Host........ 25501 bytes remaining HTTP Status. `localhost' is probably a broken 1.0 server that doesn't understand HEAD Read Socket. Target ERROR -1 Host kill... Pipeline due to HTEvent_CLOSE event ... An error is returned to my app; "This is probably a HTTP server 0.9 or less".
Received on Monday, 3 March 2003 14:23:07 UTC