From a1d1114cb26fb9038eea38f7b41a2b7f7f5ce285 Mon Sep 17 00:00:00 2001 From: Peter Surda Date: Fri, 10 Mar 2017 23:56:38 +0100 Subject: [PATCH] New network subsystem updates - auto-select select/poll/epoll/kqueue depending on what's available --- src/network/asyncore_pollchoose.py | 43 ++++++++++++++++++++++++------ src/network/http.py | 4 +-- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/network/asyncore_pollchoose.py b/src/network/asyncore_pollchoose.py index 19ec9f42..fc562671 100644 --- a/src/network/asyncore_pollchoose.py +++ b/src/network/asyncore_pollchoose.py @@ -172,7 +172,10 @@ def poll_poller(timeout=0.0, map=None): if timeout is not None: # timeout is in milliseconds timeout = int(timeout*1000) - pollster = select.poll() + try: + poll_poller.pollster + except AttributeError: + poll_poller.pollster = select.poll() if map: for fd, obj in list(map.items()): flags = 0 @@ -182,9 +185,12 @@ def poll_poller(timeout=0.0, map=None): if obj.writable() and not obj.accepting: flags |= select.POLLOUT if flags: - pollster.register(fd, flags) + try: + poll_poller.pollster.modify(fd, flags) + except IOError: + poll_poller.pollster.register(fd, flags) try: - r = pollster.poll(timeout) + r = poll_poller.pollster.poll(timeout) except KeyboardInterrupt: r = [] for fd, flags in r: @@ -201,7 +207,10 @@ def epoll_poller(timeout=0.0, map=None): """A poller which uses epoll(), supported on Linux 2.5.44 and newer.""" if map is None: map = socket_map - pollster = select.epoll() + try: + epoll_poller.pollster + except AttributeError: + epoll_poller.pollster = select.epoll() if map: for fd, obj in map.items(): flags = 0 @@ -213,9 +222,12 @@ def epoll_poller(timeout=0.0, map=None): # Only check for exceptions if object was either readable # or writable. flags |= select.POLLERR | select.POLLHUP | select.POLLNVAL - pollster.register(fd, flags) + try: + epoll_poller.pollster.register(fd, flags) + except IOError: + epoll_poller.pollster.modify(fd, flags) try: - r = pollster.poll(timeout) + r = epoll_poller.pollster.poll(timeout) except select.error, err: if err.args[0] != EINTR: raise @@ -265,9 +277,14 @@ def loop(timeout=30.0, use_poll=False, map=None, count=None, # code which grants backward compatibility with "use_poll" # argument which should no longer be used in favor of # "poller" - if use_poll and hasattr(select, 'poll'): + + if hasattr(select, 'epoll'): + poller = epoll_poller + elif hasattr(select, 'kqueue'): + poller = kqueue_poller + elif hasattr(select, 'poll'): poller = poll_poller - else: + elif hasattr(select, 'select'): poller = select_poller if count is None: @@ -349,6 +366,16 @@ class dispatcher: #self.log_info('closing channel %d:%s' % (fd, self)) del map[fd] self._fileno = None + try: + epoll_poller.pollster.unregister(fd) + except (AttributeError, KeyError): + # no epoll used, or not registered + pass + try: + poll_poller.pollster.unregister(fd) + except (AttributeError, KeyError): + # no poll used, or not registered + pass def create_socket(self, family=socket.AF_INET, type=socket.SOCK_STREAM): self.family_and_type = family, type diff --git a/src/network/http.py b/src/network/http.py index 184213b0..93828c83 100644 --- a/src/network/http.py +++ b/src/network/http.py @@ -20,13 +20,13 @@ class HttpConnection(AdvancedDispatcher): def state_init(self): self.write_buf += "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n" % (self.path, self.destination[0]) - print "\"%s\"" % (self.write_buf) + print "Sending %ib" % (len(self.write_buf)) self.set_state("http_request_sent", 0) return False def state_http_request_sent(self): if len(self.read_buf) > 0: - print self.read_buf + print "Received %ib" % (len(self.read_buf)) self.read_buf = b"" if not self.connected: self.set_state("close", 0)