I've investigated this bug further, and found the problem. Here is a
walk-through of it, in apt-cacher 1.6.8:

1. First, in the handle_connection() subroutine (line 243), you read in
   the request. apt-get(8) typically uses HTTP Keep-Alive for efficiency
   (i.e. download multiple files in one TCP connection), so when you're
   done with the CLIENTLINE: loop and have read in the first request, a
   handful of subsequent requests remain in the buffer (see @reqLineBuf,
   and the getRequestLine() subroutine as well) waiting to be serviced.

2. This normally works well. A file is requested, the file gets sent,
   apt-cacher loops back to the top of the REQUEST: loop (line 338), and
   proceeds to service the next request in the buffer.

3. When a Translation-en_US* file is requested, apt-cacher sees that it
   doesn't have this file, and proceeds to request it from the upstream
   repository. The repository returns 404, because---as we already
   know---
   Translation-en_US* files don't exist.

4. But here's what happens: Look in return_file(), line 839. Here, it
   checks the HTTP status code ($code) from the upstream server, and
   because it's 404, and $concloseflag is false, it sets
   $concloseflag to true.

5. This has effect way back up in handle_connection(), line 339. The
   loop condition is no longer true, so it exits. No further requests
   are read in, and the connection is subsequently closed.

6. Just one small problem---there are still a number of outstanding
   requests in @reqLineBuf waiting to be serviced! The "Connection reset
   by peer" error message reflects apt-get(8)'s confusion at seeing the
   connection closed prematurely.


The following modification narrowly fixes the behavior as described in
the original bug report:

--- apt-cacher-1.6.8/apt-cacher2        2009-02-22 15:30:20.000000000
-0500
+++ apt-cacher-1.6.8/apt-cacher2.fixed  2009-08-14 13:30:37.000000000
-0400
@@ -836,7 +836,7 @@
 
                # keep alive or not?
                # If error, force close
-               if ($code!=200 && !$concloseflag) {
+               if ($code!=200 && $code!=404 && !$concloseflag) {
                  debug_message("Got $code error. Going to close connection.");
                  $concloseflag=1;
                }

More generally, I believe this very notion of closing the (client)
connection on an upstream server error is faulty---a client making use
of Keep-Alive will expect the HTTP error header to be returned, and then
further requests to be fulfilled on the same connection. Maybe there are
some instances where you do want to drop the connection immediately, but
I can't think offhand of any problem [that is specific to the upstream
server] that should trigger this.

P.S.: A workaround for this bug, that doesn't involve source
modifications or locale tinkering, is to disable apt-get(8)'s use of
Keep-Alive by setting

    Acquire::http::Pipeline-Depth "0";

in e.g. /etc/apt/apt.conf.d/99workaround-for-bug517761 .



-- 
To UNSUBSCRIBE, email to [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]

Reply via email to