eventlet/gevent doesn't work well with select.poll because select.poll blocks python interpreter as a whole instead of switching from the current thread which is about to block to other runnable thread. So ovsdb python binding can't be used with eventlet/gevent. Emulate select.poll with select.select because using python means that performance isn't so important.
Signed-off-by: Isaku Yamahata <yamah...@valinux.co.jp> --- change v1 -> v2: - replace select.poll with select.select for simplicity instead of monkey patching --- python/ovs/poller.py | 71 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 69 insertions(+), 2 deletions(-) diff --git a/python/ovs/poller.py b/python/ovs/poller.py index e459c58..e4294e3 100644 --- a/python/ovs/poller.py +++ b/python/ovs/poller.py @@ -13,13 +13,80 @@ # limitations under the License. import errno -import select import ovs.timeval import ovs.vlog +import select +import socket vlog = ovs.vlog.Vlog("poller") +# eventlet/gevent that does monkey patch to select module doesn't support +# select.poll. If select.poll is used, python interpreter is blocked as a +# whole instead of switching from the current thread that is about to block +# to other runnable thread. +# So emulate select.poll by select.select because python is used so that +# performance isn't so important. +# If eventlet/gevent isn't used, we can use select.poll by replacing +# SelectPoll with select.poll class +# SelectPoll = select.poll +class _SelectSelect(object): + """ select.poll emulation by using select.select. + Only register and poll are needed at the moment. + """ + def __init__(self): + super(_SelectSelect, self).__init__() + self.rlist = [] + self.wlist = [] + self.xlist = [] + + def register(self, fd, events): + if isinstance(fd, socket.socket): + fd = fd.fileno() + assert isinstance(fd, int) + if events & select.POLLIN: + self.rlist.append(fd) + events &= ~select.POLLIN + if events & select.POLLOUT: + self.wlist.append(fd) + events &= ~select.POLLOUT + if events: + self.xlist.append(fd) + + @staticmethod + def _events_update(events_dict, fd, event): + """Emulate 'collections.defaultdict(int)[fd] |= event' with dict""" + events = events_dict.setdefault(fd, 0) + events_dict[fd] = events | event + + def poll(self, timeout): + if timeout == -1: + # epoll uses -1 for indifinite timeout, select uses None. + timeout = None + else: + timeout = float(timeout) / 1000 + + rlist, wlist, xlist = select.select(self.rlist, self.wlist, self.xlist, + timeout) + # collections.defaultdict is introduced by python 2.5 and + # XenServer uses python 2.4. We don't use it for XenServer. + # events_dict = collections.defaultdict(int) + # events_dict[fd] |= event + events_dict = {} + for fd in rlist: + self._events_update(events_dict, fd, select.POLLIN) + for fd in wlist: + self._events_update(events_dict, fd, select.POLLOUT) + for fd in xlist: + self._events_update(events_dict, fd, select.POLLERR | + select.POLLHUP | select.POLLNVAL) + return [(fd, events) for (fd, events) in events_dict.items()] + + +SelectPoll = _SelectSelect +# SelectPoll = select.poll + + class Poller(object): """High-level wrapper around the "poll" system call. @@ -122,5 +189,5 @@ class Poller(object): vlog.dbg("%s on fd %d" % (s, fd)) def __reset(self): - self.poll = select.poll() + self.poll = SelectPoll() self.timeout = -1 -- 1.7.1.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev