common.py
Go to the documentation of this file.
00001 """Lowest-common-denominator implementations of platform functionality."""
00002 from __future__ import absolute_import, division, print_function, with_statement
00003 
00004 import errno
00005 import socket
00006 
00007 from tornado.platform import interface
00008 
00009 
00010 class Waker(interface.Waker):
00011     """Create an OS independent asynchronous pipe.
00012 
00013     For use on platforms that don't have os.pipe() (or where pipes cannot
00014     be passed to select()), but do have sockets.  This includes Windows
00015     and Jython.
00016     """
00017     def __init__(self):
00018         # Based on Zope select_trigger.py:
00019         # https://github.com/zopefoundation/Zope/blob/master/src/ZServer/medusa/thread/select_trigger.py
00020 
00021         self.writer = socket.socket()
00022         # Disable buffering -- pulling the trigger sends 1 byte,
00023         # and we want that sent immediately, to wake up ASAP.
00024         self.writer.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
00025 
00026         count = 0
00027         while 1:
00028             count += 1
00029             # Bind to a local port; for efficiency, let the OS pick
00030             # a free port for us.
00031             # Unfortunately, stress tests showed that we may not
00032             # be able to connect to that port ("Address already in
00033             # use") despite that the OS picked it.  This appears
00034             # to be a race bug in the Windows socket implementation.
00035             # So we loop until a connect() succeeds (almost always
00036             # on the first try).  See the long thread at
00037             # http://mail.zope.org/pipermail/zope/2005-July/160433.html
00038             # for hideous details.
00039             a = socket.socket()
00040             a.bind(("127.0.0.1", 0))
00041             a.listen(1)
00042             connect_address = a.getsockname()  # assigned (host, port) pair
00043             try:
00044                 self.writer.connect(connect_address)
00045                 break    # success
00046             except socket.error as detail:
00047                 if (not hasattr(errno, 'WSAEADDRINUSE') or
00048                         detail[0] != errno.WSAEADDRINUSE):
00049                     # "Address already in use" is the only error
00050                     # I've seen on two WinXP Pro SP2 boxes, under
00051                     # Pythons 2.3.5 and 2.4.1.
00052                     raise
00053                 # (10048, 'Address already in use')
00054                 # assert count <= 2 # never triggered in Tim's tests
00055                 if count >= 10:  # I've never seen it go above 2
00056                     a.close()
00057                     self.writer.close()
00058                     raise socket.error("Cannot bind trigger!")
00059                 # Close `a` and try again.  Note:  I originally put a short
00060                 # sleep() here, but it didn't appear to help or hurt.
00061                 a.close()
00062 
00063         self.reader, addr = a.accept()
00064         self.reader.setblocking(0)
00065         self.writer.setblocking(0)
00066         a.close()
00067         self.reader_fd = self.reader.fileno()
00068 
00069     def fileno(self):
00070         return self.reader.fileno()
00071 
00072     def write_fileno(self):
00073         return self.writer.fileno()
00074 
00075     def wake(self):
00076         try:
00077             self.writer.send(b"x")
00078         except (IOError, socket.error):
00079             pass
00080 
00081     def consume(self):
00082         try:
00083             while True:
00084                 result = self.reader.recv(1024)
00085                 if not result:
00086                     break
00087         except (IOError, socket.error):
00088             pass
00089 
00090     def close(self):
00091         self.reader.close()
00092         self.writer.close()


rosbridge_tools
Author(s): Jonathan Mace
autogenerated on Sat Dec 27 2014 11:25:59