diff --git a/lib/http/__init__.py b/lib/http/__init__.py
index 4233b480af05e855a862b5fe6b7ceddc234e6a67..4da7f7b20e81da0e3f842b9480ef3e6e79817967 100644
--- a/lib/http/__init__.py
+++ b/lib/http/__init__.py
@@ -81,6 +81,15 @@ class HttpError(Exception):
   """
 
 
+class HttpConnectionClosed(Exception):
+  """Internal exception for a closed connection.
+
+  This should only be used for internal error reporting. Only use
+  it if there's no other way to report this condition.
+
+  """
+
+
 class HttpSocketTimeout(Exception):
   """Internal exception for socket timeouts.
 
@@ -276,6 +285,21 @@ def SocketOperation(poller, sock, op, arg1, timeout):
       except OpenSSL.SSL.WantX509LookupError:
         continue
 
+      except OpenSSL.SSL.ZeroReturnError, err:
+        # SSL Connection has been closed. In SSL 3.0 and TLS 1.0, this only
+        # occurs if a closure alert has occurred in the protocol, i.e. the
+        # connection has been closed cleanly. Note that this does not
+        # necessarily mean that the transport layer (e.g. a socket) has been
+        # closed.
+        if op == SOCKOP_SEND:
+          # Can happen during a renegotiation
+          raise HttpConnectionClosed(err.args)
+        elif op == SOCKOP_RECV:
+          return ""
+
+        # SSL_shutdown shouldn't return SSL_ERROR_ZERO_RETURN
+        raise socket.error(err.args)
+
       except OpenSSL.SSL.SysCallError, err:
         if op == SOCKOP_SEND:
           # arg1 is the data when writing
@@ -336,6 +360,7 @@ def ShutdownConnection(poller, sock, close_timeout, write_timeout, msgreader,
 
   # Close the connection from our side
   try:
+    # We don't care about the return value, see NOTES in SSL_shutdown(3).
     SocketOperation(poller, sock, SOCKOP_SHUTDOWN, socket.SHUT_RDWR,
                     write_timeout)
   except HttpSocketTimeout: