From ed815d9bd28422a490fe370d7804d24bcd676806 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Wed, 5 Sep 2012 19:38:26 +0900 Subject: [PATCH] python/ovs/poller: use select.select instead of select.poll. 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 Signed-off-by: Ben Pfaff --- python/ovs/poller.py | 63 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/python/ovs/poller.py b/python/ovs/poller.py index e459c5823..5c89f231f 100644 --- a/python/ovs/poller.py +++ b/python/ovs/poller.py @@ -13,13 +13,72 @@ # 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 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 using python means that +# performance isn't so important. +class _SelectSelect(object): + """ select.poll emulation by using select.select. + Only register and poll are needed at the moment. + """ + def __init__(self): + 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) + + def poll(self, timeout): + if timeout == -1: + # epoll uses -1 for infinite 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: + events_dict[fd] = events_dict.get(fd, 0) | select.POLLIN + for fd in wlist: + events_dict[fd] = events_dict.get(fd, 0) | select.POLLOUT + for fd in xlist: + events_dict[fd] = events_dict.get(fd, 0) | (select.POLLERR | + select.POLLHUP | + select.POLLNVAL) + return events_dict.items() + + +_SelectPoll = _SelectSelect +# If eventlet/gevent isn't used, we can use select.poll by replacing +# _SelectPoll with select.poll class +# _SelectPoll = select.poll + + class Poller(object): """High-level wrapper around the "poll" system call. @@ -122,5 +181,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 -- 2.43.0