python/ovs/poller.py: workaround an eventlet bug
[sliver-openvswitch.git] / python / ovs / poller.py
index 5c89f23..ffd6a39 100644 (file)
@@ -18,8 +18,22 @@ import ovs.vlog
 import select
 import socket
 
+try:
+    import eventlet.patcher
+
+    def _using_eventlet_green_select():
+        return eventlet.patcher.is_monkey_patched(select)
+except:
+    def _using_eventlet_green_select():
+        return False
+
 vlog = ovs.vlog.Vlog("poller")
 
+POLLIN = 0x001
+POLLOUT = 0x004
+POLLERR = 0x008
+POLLHUP = 0x010
+POLLNVAL = 0x020
 
 # eventlet/gevent doesn't support select.poll. If select.poll is used,
 # python interpreter is blocked as a whole instead of switching from the
@@ -39,12 +53,12 @@ class _SelectSelect(object):
         if isinstance(fd, socket.socket):
             fd = fd.fileno()
         assert isinstance(fd, int)
-        if events & select.POLLIN:
+        if events & POLLIN:
             self.rlist.append(fd)
-            events &= ~select.POLLIN
-        if events & select.POLLOUT:
+            events &= ~POLLIN
+        if events & POLLOUT:
             self.wlist.append(fd)
-            events &= ~select.POLLOUT
+            events &= ~POLLOUT
         if events:
             self.xlist.append(fd)
 
@@ -54,6 +68,10 @@ class _SelectSelect(object):
             timeout = None
         else:
             timeout = float(timeout) / 1000
+        # XXX workaround a bug in eventlet
+        # see https://github.com/eventlet/eventlet/pull/25
+        if timeout == 0 and _using_eventlet_green_select():
+            timeout = 0.1
 
         rlist, wlist, xlist = select.select(self.rlist, self.wlist, self.xlist,
                                             timeout)
@@ -63,17 +81,17 @@ class _SelectSelect(object):
         # events_dict[fd] |= event
         events_dict = {}
         for fd in rlist:
-            events_dict[fd] = events_dict.get(fd, 0) | select.POLLIN
+            events_dict[fd] = events_dict.get(fd, 0) | POLLIN
         for fd in wlist:
-            events_dict[fd] = events_dict.get(fd, 0) | select.POLLOUT
+            events_dict[fd] = events_dict.get(fd, 0) | POLLOUT
         for fd in xlist:
-            events_dict[fd] = events_dict.get(fd, 0) | (select.POLLERR |
-                                                        select.POLLHUP |
-                                                        select.POLLNVAL)
+            events_dict[fd] = events_dict.get(fd, 0) | (POLLERR |
+                                                        POLLHUP |
+                                                        POLLNVAL)
         return events_dict.items()
 
 
-_SelectPoll = _SelectSelect
+SelectPoll = _SelectSelect
 # If eventlet/gevent isn't used, we can use select.poll by replacing
 # _SelectPoll with select.poll class
 # _SelectPoll = select.poll
@@ -168,18 +186,18 @@ class Poller(object):
             for fd, revents in events:
                 if revents != 0:
                     s = ""
-                    if revents & select.POLLIN:
+                    if revents & POLLIN:
                         s += "[POLLIN]"
-                    if revents & select.POLLOUT:
+                    if revents & POLLOUT:
                         s += "[POLLOUT]"
-                    if revents & select.POLLERR:
+                    if revents & POLLERR:
                         s += "[POLLERR]"
-                    if revents & select.POLLHUP:
+                    if revents & POLLHUP:
                         s += "[POLLHUP]"
-                    if revents & select.POLLNVAL:
+                    if revents & POLLNVAL:
                         s += "[POLLNVAL]"
                     vlog.dbg("%s on fd %d" % (s, fd))
 
     def __reset(self):
-        self.poll = _SelectPoll()
+        self.poll = SelectPoll()
         self.timeout = -1