]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Try to fix spurious close() errors
authorAntoine Pitrou <antoine@python.org>
Thu, 3 Nov 2016 10:44:30 +0000 (11:44 +0100)
committerAntoine Pitrou <antoine@python.org>
Thu, 3 Nov 2016 10:44:30 +0000 (11:44 +0100)
tornado/ioloop.py
tornado/platform/common.py
tornado/platform/interface.py
tornado/platform/posix.py

index 006b0b4d75b989f510c2aaf6ebfe8fb79bfe7ee7..1b1a07cd5a951ce1f4fcc1448c7a0e0c1a270127 100644 (file)
@@ -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:
index 3c3f68a51906b2b02c6d7cd5f1635a250f73a462..ed539357ab29d2db1e471cd41b6753e44f606d93 100644 (file)
@@ -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)
index b133b33950a45983e5c181f809ba87a4bb6ccb39..cc062391175fee2e0346a868eecf3b8b0c248066 100644 (file)
@@ -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()
index e01f46f54cbc332fe19b0991195f88654c47b624..02fb2a35bb50b5c24ccc9db8b305399f9dafca02 100644 (file)
@@ -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)