- 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