From: Ben Darnell Date: Sat, 25 May 2013 19:26:37 +0000 (-0400) Subject: Use remove and add instead of update_handler in curl_httpclient. X-Git-Tag: v3.1.0~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=94198facc300623e05c7eb6465794c0635ecadfa;p=thirdparty%2Ftornado.git Use remove and add instead of update_handler in curl_httpclient. Curl sometimes fails to tell us that it has closed a socket and reopened a new one with the same file descriptor, leading to problems in some IOLoops. This should fix the recurring problem of update_handler errors in various less-common use cases. Closes #801. Closes #538. --- diff --git a/tornado/curl_httpclient.py b/tornado/curl_httpclient.py index 7d063b771..e09005691 100644 --- a/tornado/curl_httpclient.py +++ b/tornado/curl_httpclient.py @@ -111,13 +111,19 @@ class CurlAsyncHTTPClient(AsyncHTTPClient): del self._fds[fd] else: ioloop_event = event_map[event] - if fd not in self._fds: - self.io_loop.add_handler(fd, self._handle_events, - ioloop_event) - self._fds[fd] = ioloop_event - else: - self.io_loop.update_handler(fd, ioloop_event) - self._fds[fd] = ioloop_event + # libcurl sometimes closes a socket and then opens a new + # one using the same FD without giving us a POLL_NONE in + # between. This is a problem with the epoll IOLoop, + # because the kernel can tell when a socket is closed and + # removes it from the epoll automatically, causing future + # update_handler calls to fail. Since we can't tell when + # this has happened, always use remove and re-add + # instead of update. + if fd in self._fds: + self.io_loop.remove_handler(fd) + self.io_loop.add_handler(fd, self._handle_events, + ioloop_event) + self._fds[fd] = ioloop_event def _set_timeout(self, msecs): """Called by libcurl to schedule a timeout."""