web/filenode.py: avoid calling req.finish() on closed HTTP connections. Closes #1366
authorBrian Warner <warner@lothar.com>
Mon, 21 Feb 2011 06:15:44 +0000 (22:15 -0800)
committerBrian Warner <warner@lothar.com>
Mon, 21 Feb 2011 06:15:44 +0000 (22:15 -0800)
src/allmydata/web/filenode.py

index e872e1e0535609b3847e5b6a0d92d9c3f89bdb24..66b7df0830fc20ca92325df2e4727def9bd4f5a7 100644 (file)
@@ -444,10 +444,27 @@ class FileDownloader(rend.Page):
         req.setHeader("content-length", str(contentsize))
         if req.method == "HEAD":
             return ""
+
+        # Twisted >=9.0 throws an error if we call req.finish() on a closed
+        # HTTP connection. It also has req.notifyFinish() to help avoid it.
+        finished = []
+        def _request_finished(ign):
+            finished.append(True)
+        if hasattr(req, "notifyFinish"):
+            req.notifyFinish().addBoth(_request_finished)
+
         d = self.filenode.read(req, first, size)
+
+        def _finished(ign):
+            if not finished:
+                req.finish()
         def _error(f):
-            log.msg("error during GET", facility="tahoe.webish", failure=f,
-                    level=log.UNUSUAL, umid="xSiF3w")
+            lp = log.msg("error during GET", facility="tahoe.webish", failure=f,
+                         level=log.UNUSUAL, umid="xSiF3w")
+            if finished:
+                log.msg("but it's too late to tell them", parent=lp,
+                        level=log.UNUSUAL, umid="j1xIbw")
+                return
             req._tahoe_request_had_error = f # for HTTP-style logging
             if req.startedWriting:
                 # The content-type is already set, and the response code has
@@ -466,7 +483,7 @@ class FileDownloader(rend.Page):
                 # sensible error message.
                 eh = MyExceptionHandler()
                 eh.renderHTTP_exception(ctx, f)
-        d.addCallbacks(lambda ign: req.finish(), _error)
+        d.addCallbacks(_finished, _error)
         return req.deferred