[PATCH] Close lingering connections after receiving an HTTP error 401, to prevent socket exhaustion (issue1979)

Kevin Gessner kevin at kevingessner.com
Thu Feb 18 15:24:36 CST 2010


This patch works around what appears to be a bug in urllib2, which leaks connections on HTTP 401 errors. hg's urllib2.OpenerDirector, which connects to remote repos, uses an urllib2.HTTPBasicAuthHandler to handle HTTP 401 errors. That handler creates a new, authenticated request, but never closes the old connection. The handler in this patch catches these errors first, closes the existing connection, and then passes control along to the other handlers, fixing the socket exhaustion seen in issue 1979.

---

# HG changeset patch
# User "Kevin Gessner <kevin at kevingessner.com>"
# Date 1266526400 18000
# Node ID 24712d83208603a2fc2bac577d734841e60476ab
# Parent  74331292e230c6c449f5ebd3076ecb3430e9ece9
Close lingering connections after receiving an HTTP error 401, to prevent socket exhaustion (issue1979)

diff -r 74331292e230 -r 24712d832086 mercurial/url.py
--- a/mercurial/url.py	Wed Feb 17 23:10:22 2010 +0100
+++ b/mercurial/url.py	Thu Feb 18 15:53:20 2010 -0500
@@ -566,12 +566,23 @@
 
 handlerfuncs = []
 
+class keep_alive_cleanup_handler(urllib2.BaseHandler):
+    """
+    urllib2-compatible handler catches error 401 and closes the
+    existing connection. this prevents mercurial from leaking these
+    connections. returns None to allow the next error handler to
+    act.
+    """
+    def http_error_401(self, req, fp, code, msg, headers):
+        fp.close()
+        return None
+
 def opener(ui, authinfo=None):
     '''
     construct an opener suitable for urllib2
     authinfo will be added to the password manager
     '''
-    handlers = [httphandler()]
+    handlers = [httphandler(), keep_alive_cleanup_handler()]
     if has_https:
         handlers.append(httpshandler(ui))


More information about the Mercurial-devel mailing list