]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Implementing suggested changes
authorunknown <mgenti@.(none)>
Tue, 23 Mar 2010 14:29:46 +0000 (09:29 -0500)
committerunknown <mgenti@.(none)>
Tue, 23 Mar 2010 14:29:46 +0000 (09:29 -0500)
tornado/fcntl_win32.py [deleted file]
tornado/httpserver.py
tornado/ioloop.py
tornado/win32_support.py [new file with mode: 0644]

diff --git a/tornado/fcntl_win32.py b/tornado/fcntl_win32.py
deleted file mode 100644 (file)
index 2dfdae4..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-import ctypes
-import ctypes.wintypes
-import os
-
-
-# See: http://msdn.microsoft.com/en-us/library/ms738573(VS.85).aspx
-ioctlsocket = ctypes.windll.ws2_32.ioctlsocket
-ioctlsocket.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.LONG, ctypes.wintypes.ULONG)
-ioctlsocket.restype = ctypes.c_int
-
-# See: http://msdn.microsoft.com/en-us/library/ms724935(VS.85).aspx
-SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
-SetHandleInformation.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD)
-SetHandleInformation.restype = ctypes.wintypes.BOOL
-
-HANDLE_FLAG_INHERIT = 0x00000001
-
-
-F_GETFD = 1
-F_SETFD = 2
-F_GETFL = 3
-F_SETFL = 4
-
-FD_CLOEXEC = 1
-
-os.O_NONBLOCK = 2048
-
-FIONBIO = 126
-
-
-def fcntl(fd, op, arg=0):
-    if op == F_GETFD or op == F_GETFL:
-        return 0
-    elif op == F_SETFD:
-        # Check that the flag is CLOEXEC and translate
-        if arg == FD_CLOEXEC:
-            success = SetHandleInformation(fd, HANDLE_FLAG_INHERIT, arg)
-            if not success:
-                raise ctypes.GetLastError()
-        else:
-            raise ValueError("Unsupported arg")
-    #elif op == F_SETFL:
-        ## Check that the flag is NONBLOCK and translate
-        #if arg == os.O_NONBLOCK:
-            ##pass
-            #result = ioctlsocket(fd, FIONBIO, 1)
-            #if result != 0:
-                #raise ctypes.GetLastError()
-        #else:
-            #raise ValueError("Unsupported arg")
-    else:
-        raise ValueError("Unsupported op")
index 178d8e9d8f704667658a2b6ba39e903575e63b75..60af4d96f828e8be13e21bb7cb5cc25df0449f66 100644 (file)
@@ -23,7 +23,7 @@ try:
 except ImportError:
     import sys
     if sys.platform.startswith("win"):
-        import fcntl_win32 as fcntl
+        import win32_support as fcntl
     else:
         raise
 import functools
index 9f43b29554daca053e906728e88e7f9308d73bfc..9a7ea709d472bb3d45f03ef315ef9013d69a12fc 100644 (file)
@@ -23,7 +23,8 @@ try:
     import fcntl
 except ImportError:
     if os.name != 'posix':
-        import socket
+        import win32_support
+        import win32_support as fcntl
     else:
         raise
 import logging
@@ -31,83 +32,6 @@ import select
 import time
 
 
-class Pipe(object):
-    """Create an OS independent asynchronous pipe"""
-    def __init__(self):
-        self.reader = None
-        self.writer = None
-        self.reader_fd = -1
-        if os.name == 'posix':
-            self.reader_fd, w = os.pipe()
-            IOLoop.set_nonblocking(self.reader_fd)
-            IOLoop.set_nonblocking(w)
-            IOLoop.set_close_exec(self.reader_fd)
-            IOLoop.set_close_exec(w)
-            self.reader = os.fdopen(self.reader_fd, "r", 0)
-            self.writer = os.fdopen(w, "w", 0)
-        else:
-            # Based on Zope async.py: http://svn.zope.org/zc.ngi/trunk/src/zc/ngi/async.py
-
-            self.writer = socket.socket()
-            # Disable buffering -- pulling the trigger sends 1 byte,
-            # and we want that sent immediately, to wake up asyncore's
-            # select() ASAP.
-            self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
-
-            count = 0
-            while 1:
-                count += 1
-                # Bind to a local port; for efficiency, let the OS pick
-                # a free port for us.
-                # Unfortunately, stress tests showed that we may not
-                # be able to connect to that port ("Address already in
-                # use") despite that the OS picked it.  This appears
-                # to be a race bug in the Windows socket implementation.
-                # So we loop until a connect() succeeds (almost always
-                # on the first try).  See the long thread at
-                # http://mail.zope.org/pipermail/zope/2005-July/160433.html
-                # for hideous details.
-                a = socket.socket()
-                a.bind(("127.0.0.1", 0))
-                connect_address = a.getsockname()  # assigned (host, port) pair
-                a.listen(1)
-                try:
-                    self.writer.connect(connect_address)
-                    break    # success
-                except socket.error, detail:
-                    if detail[0] != errno.WSAEADDRINUSE:
-                        # "Address already in use" is the only error
-                        # I've seen on two WinXP Pro SP2 boxes, under
-                        # Pythons 2.3.5 and 2.4.1.
-                        raise
-                    # (10048, 'Address already in use')
-                    # assert count <= 2 # never triggered in Tim's tests
-                    if count >= 10:  # I've never seen it go above 2
-                        a.close()
-                        self.writer.close()
-                        raise BindError("Cannot bind trigger!")
-                    # Close `a` and try again.  Note:  I originally put a short
-                    # sleep() here, but it didn't appear to help or hurt.
-                    a.close()
-
-            self.reader, addr = a.accept()
-            self.reader.setblocking(0)
-            self.writer.setblocking(0)
-            a.close()
-            self.reader_fd = self.reader.fileno()
-
-    def read(self):
-        try:
-            return self.reader.recv(1)
-        except socket.error, ex:
-            if ex.args[0] == errno.EWOULDBLOCK:
-                raise IOError
-            raise
-
-    def write(self, data):
-        return self.writer.send(data)
-
-
 class IOLoop(object):
     """A level-triggered I/O loop.
 
@@ -165,7 +89,7 @@ class IOLoop(object):
     def __init__(self, impl=None):
         self._impl = impl or _poll()
         if hasattr(self._impl, 'fileno'):
-            self.set_close_exec(self._impl.fileno())
+            self._set_close_exec(self._impl.fileno())
         self._handlers = {}
         self._events = {}
         self._callbacks = set()
@@ -175,9 +99,18 @@ class IOLoop(object):
 
         # Create a pipe that we send bogus data to when we want to wake
         # the I/O loop when it is idle
-        trigger = Pipe()
-        self._waker_reader = self._waker_writer = trigger
-        self.add_handler(trigger.reader_fd, self._read_waker, self.READ)
+        if os.name == 'posix':
+            r, w = os.pipe()
+            self._set_nonblocking(r)
+            self._set_nonblocking(w)
+            self._set_close_exec(r)
+            self._set_close_exec(w)
+            self._waker_reader = os.fdopen(r, "r", 0)
+            self._waker_writer = os.fdopen(w, "w", 0)
+        else:
+            pipe = win32_support.Pipe()
+            r = pipe.reader_fd
+        self.add_handler(r, self._read_waker, self.READ)
 
     @classmethod
     def instance(cls):
@@ -364,13 +297,11 @@ class IOLoop(object):
         except IOError:
             pass
 
-    @staticmethod
-    def set_nonblocking(fd):
+    def _set_nonblocking(self, fd):
         flags = fcntl.fcntl(fd, fcntl.F_GETFL)
         fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
 
-    @staticmethod
-    def set_close_exec(fd):
+    def _set_close_exec(self, fd):
         flags = fcntl.fcntl(fd, fcntl.F_GETFD)
         fcntl.fcntl(fd, fcntl.F_SETFD, flags | fcntl.FD_CLOEXEC)
 
diff --git a/tornado/win32_support.py b/tornado/win32_support.py
new file mode 100644 (file)
index 0000000..88cfc16
--- /dev/null
@@ -0,0 +1,119 @@
+import ctypes
+import ctypes.wintypes
+import os
+import socket
+
+
+# See: http://msdn.microsoft.com/en-us/library/ms738573(VS.85).aspx
+ioctlsocket = ctypes.windll.ws2_32.ioctlsocket
+ioctlsocket.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.LONG, ctypes.wintypes.ULONG)
+ioctlsocket.restype = ctypes.c_int
+
+# See: http://msdn.microsoft.com/en-us/library/ms724935(VS.85).aspx
+SetHandleInformation = ctypes.windll.kernel32.SetHandleInformation
+SetHandleInformation.argtypes = (ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, ctypes.wintypes.DWORD)
+SetHandleInformation.restype = ctypes.wintypes.BOOL
+
+HANDLE_FLAG_INHERIT = 0x00000001
+
+
+F_GETFD = 1
+F_SETFD = 2
+F_GETFL = 3
+F_SETFL = 4
+
+FD_CLOEXEC = 1
+
+os.O_NONBLOCK = 2048
+
+FIONBIO = 126
+
+
+def fcntl(fd, op, arg=0):
+    if op == F_GETFD or op == F_GETFL:
+        return 0
+    elif op == F_SETFD:
+        # Check that the flag is CLOEXEC and translate
+        if arg == FD_CLOEXEC:
+            success = SetHandleInformation(fd, HANDLE_FLAG_INHERIT, arg)
+            if not success:
+                raise ctypes.GetLastError()
+        else:
+            raise ValueError("Unsupported arg")
+    #elif op == F_SETFL:
+        ## Check that the flag is NONBLOCK and translate
+        #if arg == os.O_NONBLOCK:
+            ##pass
+            #result = ioctlsocket(fd, FIONBIO, 1)
+            #if result != 0:
+                #raise ctypes.GetLastError()
+        #else:
+            #raise ValueError("Unsupported arg")
+    else:
+        raise ValueError("Unsupported op")
+
+
+class Pipe(object):
+    """Create an OS independent asynchronous pipe"""
+    def __init__(self):
+        # Based on Zope async.py: http://svn.zope.org/zc.ngi/trunk/src/zc/ngi/async.py
+
+        self.writer = socket.socket()
+        # Disable buffering -- pulling the trigger sends 1 byte,
+        # and we want that sent immediately, to wake up ASAP.
+        self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+
+        count = 0
+        while 1:
+            count += 1
+            # Bind to a local port; for efficiency, let the OS pick
+            # a free port for us.
+            # Unfortunately, stress tests showed that we may not
+            # be able to connect to that port ("Address already in
+            # use") despite that the OS picked it.  This appears
+            # to be a race bug in the Windows socket implementation.
+            # So we loop until a connect() succeeds (almost always
+            # on the first try).  See the long thread at
+            # http://mail.zope.org/pipermail/zope/2005-July/160433.html
+            # for hideous details.
+            a = socket.socket()
+            a.bind(("127.0.0.1", 0))
+            connect_address = a.getsockname()  # assigned (host, port) pair
+            a.listen(1)
+            try:
+                self.writer.connect(connect_address)
+                break    # success
+            except socket.error, detail:
+                if detail[0] != errno.WSAEADDRINUSE:
+                    # "Address already in use" is the only error
+                    # I've seen on two WinXP Pro SP2 boxes, under
+                    # Pythons 2.3.5 and 2.4.1.
+                    raise
+                # (10048, 'Address already in use')
+                # assert count <= 2 # never triggered in Tim's tests
+                if count >= 10:  # I've never seen it go above 2
+                    a.close()
+                    self.writer.close()
+                    raise BindError("Cannot bind trigger!")
+                # Close `a` and try again.  Note:  I originally put a short
+                # sleep() here, but it didn't appear to help or hurt.
+                a.close()
+
+        self.reader, addr = a.accept()
+        self.reader.setblocking(0)
+        self.writer.setblocking(0)
+        a.close()
+        self.reader_fd = self.reader.fileno()
+
+    def read(self):
+        """Emulate a file descriptors read method"""
+        try:
+            return self.reader.recv(1)
+        except socket.error, ex:
+            if ex.args[0] == errno.EWOULDBLOCK:
+                raise IOError
+            raise
+
+    def write(self, data):
+        """Emulate a file descriptors write method"""
+        return self.writer.send(data)