From: Antoine Pitrou Date: Thu, 3 Nov 2016 10:44:30 +0000 (+0100) Subject: Try to fix spurious close() errors X-Git-Tag: v4.5.0~61^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d509f72d54caf8ee70f446e1d90ddbdabfd5d6d0;p=thirdparty%2Ftornado.git Try to fix spurious close() errors --- diff --git a/tornado/ioloop.py b/tornado/ioloop.py index 006b0b4d7..1b1a07cd5 100644 --- a/tornado/ioloop.py +++ b/tornado/ioloop.py @@ -712,7 +712,6 @@ class PollIOLoop(IOLoop): self.READ) def close(self, all_fds=False): - self._waker.mark_closing() self._closing = True self.remove_handler(self._waker.fileno()) if all_fds: diff --git a/tornado/platform/common.py b/tornado/platform/common.py index 3c3f68a51..ed539357a 100644 --- a/tornado/platform/common.py +++ b/tornado/platform/common.py @@ -3,10 +3,26 @@ from __future__ import absolute_import, division, print_function, with_statement import errno import socket +import time from tornado.platform import interface +def try_close(f): + # Avoid issue #875 (race condition when using the file in another + # thread). + for i in range(10): + try: + f.close() + except IOError: + # Yield to another thread + time.sleep(1e-3) + else: + break + # Try a last time and let raise + f.close() + + class Waker(interface.Waker): """Create an OS independent asynchronous pipe. @@ -18,7 +34,6 @@ class Waker(interface.Waker): # Based on Zope select_trigger.py: # https://github.com/zopefoundation/Zope/blob/master/src/ZServer/medusa/thread/select_trigger.py - self.closing = False self.writer = socket.socket() # Disable buffering -- pulling the trigger sends 1 byte, # and we want that sent immediately, to wake up ASAP. @@ -74,10 +89,6 @@ class Waker(interface.Waker): return self.writer.fileno() def wake(self): - if self.closing: - # Avoid issue #875 (race condition when closing the fd in another - # thread). - return try: self.writer.send(b"x") except (IOError, socket.error): @@ -94,7 +105,4 @@ class Waker(interface.Waker): def close(self): self.reader.close() - self.writer.close() - - def mark_closing(self): - self.closing = True + try_close(self.writer) diff --git a/tornado/platform/interface.py b/tornado/platform/interface.py index b133b3395..cc0623911 100644 --- a/tornado/platform/interface.py +++ b/tornado/platform/interface.py @@ -62,10 +62,5 @@ class Waker(object): """Closes the waker's file descriptor(s).""" raise NotImplementedError() - def mark_closing(self): - """Mark the waker as closing.""" - raise NotImplementedError() - - def monotonic_time(): raise NotImplementedError() diff --git a/tornado/platform/posix.py b/tornado/platform/posix.py index e01f46f54..02fb2a35b 100644 --- a/tornado/platform/posix.py +++ b/tornado/platform/posix.py @@ -21,7 +21,7 @@ from __future__ import absolute_import, division, print_function, with_statement import fcntl import os -from tornado.platform import interface +from tornado.platform import common, interface def set_close_exec(fd): @@ -36,7 +36,6 @@ def _set_nonblocking(fd): class Waker(interface.Waker): def __init__(self): - self.closing = False r, w = os.pipe() _set_nonblocking(r) _set_nonblocking(w) @@ -52,10 +51,6 @@ class Waker(interface.Waker): return self.writer.fileno() def wake(self): - if self.closing: - # Avoid issue #875 (race condition when closing the fd in another - # thread). - return try: self.writer.write(b"x") except IOError: @@ -72,7 +67,4 @@ class Waker(interface.Waker): def close(self): self.reader.close() - self.writer.close() - - def mark_closing(self): - self.closing = True + common.try_close(self.writer)