Example #1
0
    def runloop(self, timeout):
        """
        Run epoll main loop.
        """
        if not timeout:
            timeout = -1

        start_time = time.time()

        # run main event loop...
        while self.evlooprefcnt > 0:
            self._debug("LOOP evlooprefcnt=%d (reg_clifds=%s) (timers=%d)" % \
                    (self.evlooprefcnt, self.reg_clifds.keys(),
                     len(self.timerq)))
            try:
                timeo = self.timerq.nextfire_delay()
                if timeout > 0 and timeo >= timeout:
                    # task timeout may invalidate clients timeout
                    self.timerq.clear()
                    timeo = timeout
                elif timeo == -1:
                    timeo = timeout

                self._current_loopcnt += 1
                evlist = self.epolling.poll(timeo + 0.001)

            except IOError, ex:
                # might get interrupted by a signal
                if ex.errno == errno.EINTR:
                    continue

            for fd, event in evlist:

                # get client instance
                client, stream = self._fd2client(fd)
                if client is None:
                    continue

                fdev = stream.evmask
                fname = stream.name

                # set as current processed client
                self._current_client = client

                # check for poll error condition of some sort
                if event & select.EPOLLERR:
                    self._debug("EPOLLERR fd=%d fname=%s fdev=0x%x (%s)" % \
                                (fd, fname, fdev, client))
                    assert fdev & E_WRITE
                    self.remove_stream(client, stream)
                    self._current_client = None
                    continue

                # check for data to read
                if event & select.EPOLLIN:
                    assert fdev & E_READ
                    assert stream.events & fdev, (stream.events, fdev)
                    self.modify(client, fname, 0, fdev)
                    try:
                        client._handle_read(fname)
                    except EngineClientEOF:
                        self._debug("EngineClientEOF %s %s" % (client, fname))
                        self.remove_stream(client, stream)
                        self._current_client = None
                        continue

                # or check for end of stream (do not handle both at the same
                # time because handle_read() may perform a partial read)
                elif event & select.EPOLLHUP:
                    assert fdev & E_READ, "fdev 0x%x & E_READ" % fdev
                    self._debug("EPOLLHUP fd=%d fname=%s %s (%s)" % \
                                (fd, fname, client, client.streams))
                    self.remove_stream(client, stream)
                    self._current_client = None
                    continue

                # check for writing
                if event & select.EPOLLOUT:
                    self._debug("EPOLLOUT fd=%d fname=%s %s (%s)" % \
                                (fd, fname, client, client.streams))
                    assert fdev & E_WRITE
                    assert stream.events & fdev, (stream.events, fdev)
                    self.modify(client, fname, 0, fdev)
                    client._handle_write(fname)

                self._current_client = None

                # apply any changes occured during processing
                if client.registered:
                    self.set_events(client, stream)

            # check for task runloop timeout
            if timeout > 0 and time.time() >= start_time + timeout:
                raise EngineTimeoutException()

            # process clients timeout
            self.fire_timers()
Example #2
0
    def runloop(self, timeout):
        """
        Select engine run(): start clients and properly get replies
        """
        if not timeout:
            timeout = -1

        start_time = time.time()

        # run main event loop...
        while self.evlooprefcnt > 0:
            self._debug(
                "LOOP evlooprefcnt=%d (reg_clifds=%s) (timers=%d)" %
                (self.evlooprefcnt, self.reg_clifds.keys(), len(self.timerq)))
            try:
                timeo = self.timerq.nextfire_delay()
                if timeout > 0 and timeo >= timeout:
                    # task timeout may invalidate clients timeout
                    self.timerq.clear()
                    timeo = timeout
                elif timeo == -1:
                    timeo = timeout

                self._current_loopcnt += 1
                if timeo >= 0:
                    r_ready, w_ready, x_ready = \
                        select.select(self._fds_r, self._fds_w, [], timeo)
                else:
                    # no timeout specified, do not supply the timeout argument
                    r_ready, w_ready, x_ready = \
                        select.select(self._fds_r, self._fds_w, [])
            except select.error, (ex_errno, ex_strerror):
                # might get interrupted by a signal
                if ex_errno == errno.EINTR:
                    continue
                elif ex_errno in [errno.EINVAL, errno.EBADF, errno.ENOMEM]:
                    msg = "Increase RLIMIT_NOFILE?"
                    logging.getLogger(__name__).error(msg)
                raise

            # iterate over fd on which events occured
            for fd in set(r_ready) | set(w_ready):

                # get client instance
                client, stream = self._fd2client(fd)
                if client is None:
                    continue

                fdev = stream.evmask
                sname = stream.name

                # process this stream
                self._current_stream = stream

                # check for possible unblocking read on this fd
                if fd in r_ready:
                    self._debug(
                        "R_READY fd=%d %s (%s)" %
                        (fd, client.__class__.__name__, client.streams))
                    assert fdev & E_READ
                    assert stream.events & fdev
                    self.modify(client, sname, 0, fdev)
                    try:
                        client._handle_read(sname)
                    except EngineClientEOF:
                        self._debug("EngineClientEOF %s" % client)
                        self.remove_stream(client, stream)

                # check for writing
                if fd in w_ready:
                    self._debug(
                        "W_READY fd=%d %s (%s)" %
                        (fd, client.__class__.__name__, client.streams))
                    assert fdev == E_WRITE
                    assert stream.events & fdev
                    self.modify(client, sname, 0, fdev)
                    client._handle_write(sname)

                # post processing
                self._current_stream = None

                # apply any changes occured during processing
                if client.registered:
                    self.set_events(client, stream)

            # check for task runloop timeout
            if timeout > 0 and time.time() >= start_time + timeout:
                raise EngineTimeoutException()

            # process clients timeout
            self.fire_timers()
Example #3
0
    def runloop(self, timeout):
        """
        Select engine run(): start clients and properly get replies
        """
        if timeout == 0:
            timeout = -1

        start_time = time.time()

        # run main event loop...
        while self.evlooprefcnt > 0:
            self._debug(
                "LOOP evlooprefcnt=%d (reg_clifds=%s) (timers=%d)" %
                (self.evlooprefcnt, self.reg_clifds.keys(), len(self.timerq)))
            try:
                timeo = self.timerq.nextfire_delay()
                if timeout > 0 and timeo >= timeout:
                    # task timeout may invalidate clients timeout
                    self.timerq.clear()
                    timeo = timeout
                elif timeo == -1:
                    timeo = timeout

                self._current_loopcnt += 1
                if timeo >= 0:
                    r_ready, w_ready, x_ready = \
                        select.select(self._fds_r, self._fds_w, [], timeo)
                else:
                    # no timeout specified, do not supply the timeout argument
                    r_ready, w_ready, x_ready = \
                        select.select(self._fds_r, self._fds_w, [])
            except select.error, (ex_errno, ex_strerror):
                # might get interrupted by a signal
                if ex_errno == errno.EINTR:
                    continue
                elif ex_errno in [errno.EINVAL, errno.EBADF, errno.ENOMEM]:
                    print >> sys.stderr, "EngineSelect: %s" % ex_strerror
                else:
                    raise

            # iterate over fd on which events occured
            for fd in set(r_ready) | set(w_ready):

                # get client instance
                client, fdev = self._fd2client(fd)
                if client is None:
                    continue

                # process this client
                client._current_client = client

                # check for possible unblocking read on this fd
                if fd in r_ready:
                    assert fdev & (Engine.E_READ | Engine.E_ERROR)
                    assert client._events & fdev
                    self.modify(client, 0, fdev)
                    try:
                        if fdev & Engine.E_READ:
                            client._handle_read()
                        else:
                            client._handle_error()
                    except EngineClientEOF:
                        self._debug("EngineClientEOF %s" % client)
                        # if the EOF occurs on E_READ...
                        if fdev & Engine.E_READ:
                            # and if the client is also waiting for E_ERROR
                            if client._events & Engine.E_ERROR:
                                # just clear the event for E_READ
                                self.modify(client, 0, fdev)
                            else:
                                # otherwise we can remove the client
                                self.remove(client)
                        else:
                            # same thing in the other order...
                            if client._events & Engine.E_READ:
                                self.modify(client, 0, fdev)
                            else:
                                self.remove(client)

                # check for writing
                if fd in w_ready:
                    self._debug(
                        "W_READY fd=%d %s (r%s,e%s,w%s)" %
                        (fd, client.__class__.__name__, client.reader_fileno(),
                         client.error_fileno(), client.writer_fileno()))
                    assert fdev == Engine.E_WRITE
                    assert client._events & fdev
                    self.modify(client, 0, fdev)
                    client._handle_write()

                # post processing
                self._current_client = None

                # apply any changes occured during processing
                if client.registered:
                    self.set_events(client, client._new_events)

            # check for task runloop timeout
            if timeout > 0 and time.time() >= start_time + timeout:
                raise EngineTimeoutException()

            # process clients timeout
            self.fire_timers()
Example #4
0
    def runloop(self, timeout):
        """
        Poll engine run(): start clients and properly get replies
        """
        if not timeout:
            timeout = -1

        start_time = time.time()

        # run main event loop...
        while self.evlooprefcnt > 0:
            self._debug("LOOP evlooprefcnt=%d (reg_clifds=%s) (timers=%d)" \
                % (self.evlooprefcnt, self.reg_clifds.keys(), \
                   len(self.timerq)))
            try:
                timeo = self.timerq.nextfire_delay()
                if timeout > 0 and timeo >= timeout:
                    # task timeout may invalidate clients timeout
                    self.timerq.clear()
                    timeo = timeout
                elif timeo == -1:
                    timeo = timeout

                self._current_loopcnt += 1
                evlist = self.polling.poll(timeo * 1000.0 + 1.0)

            except select.error, (ex_errno, ex_strerror):
                # might get interrupted by a signal
                if ex_errno == errno.EINTR:
                    continue
                elif ex_errno == errno.EINVAL:
                    print >> sys.stderr, \
                            "EnginePoll: please increase RLIMIT_NOFILE"
                raise

            for fd, event in evlist:

                if event & select.POLLNVAL:
                    raise EngineException("Caught POLLNVAL on fd %d" % fd)

                # get client instance
                client, stream = self._fd2client(fd)
                if client is None:
                    continue

                fdev = stream.evmask
                sname = stream.name

                # process this stream
                self._current_stream = stream

                # check for poll error condition of some sort
                if event & select.POLLERR:
                    self._debug("POLLERR %s" % client)
                    assert fdev & E_WRITE
                    self._debug("POLLERR: remove_stream sname %s fdev 0x%x" %
                                (sname, fdev))
                    self.remove_stream(client, stream)
                    self._current_stream = None
                    continue

                # check for data to read
                if event & select.POLLIN:
                    assert fdev & E_READ
                    assert stream.events & fdev, (stream.events, fdev)
                    self.modify(client, sname, 0, fdev)
                    try:
                        client._handle_read(sname)
                    except EngineClientEOF:
                        self._debug("EngineClientEOF %s %s" % (client, sname))
                        self.remove_stream(client, stream)
                        self._current_stream = None
                        continue

                # or check for end of stream (do not handle both at the same
                # time because handle_read() may perform a partial read)
                elif event & select.POLLHUP:
                    self._debug(
                        "POLLHUP fd=%d %s (%s)" %
                        (fd, client.__class__.__name__, client.streams))
                    self.remove_stream(client, stream)
                    self._current_stream = None
                    continue

                # check for writing
                if event & select.POLLOUT:
                    self._debug(
                        "POLLOUT fd=%d %s (%s)" %
                        (fd, client.__class__.__name__, client.streams))
                    assert fdev == E_WRITE
                    assert stream.events & fdev
                    self.modify(client, sname, 0, fdev)
                    client._handle_write(sname)

                self._current_stream = None

                # apply any changes occured during processing
                if client.registered:
                    self.set_events(client, stream)

            # check for task runloop timeout
            if timeout > 0 and time.time() >= start_time + timeout:
                raise EngineTimeoutException()

            # process clients timeout
            self.fire_timers()
Example #5
0
    def runloop(self, timeout):
        """
        Run epoll main loop.
        """
        if timeout == 0:
            timeout = -1

        start_time = time.time()

        # run main event loop...
        while self.evlooprefcnt > 0:
            self._debug("LOOP evlooprefcnt=%d (reg_clifds=%s) (timers=%d)" % \
                    (self.evlooprefcnt, self.reg_clifds.keys(),
                     len(self.timerq)))
            try:
                timeo = self.timerq.nextfire_delay()
                if timeout > 0 and timeo >= timeout:
                    # task timeout may invalidate clients timeout
                    self.timerq.clear()
                    timeo = timeout
                elif timeo == -1:
                    timeo = timeout

                self._current_loopcnt += 1
                evlist = self.epolling.poll(timeo + 0.001)

            except IOError, ex:
                # might get interrupted by a signal
                if ex.errno == errno.EINTR:
                    continue

            for fd, event in evlist:

                # get client instance
                client, fdev = self._fd2client(fd)
                if client is None:
                    continue

                # set as current processed client
                self._current_client = client

                # check for poll error condition of some sort
                if event & select.EPOLLERR:
                    self._debug("EPOLLERR %s" % client)
                    client._close_writer()
                    self._current_client = None
                    continue

                # check for data to read
                if event & select.EPOLLIN:
                    #self._debug("EPOLLIN fd=%d %s" % (fd, client))
                    assert fdev & (Engine.E_READ | Engine.E_ERROR)
                    assert client._events & fdev
                    self.modify(client, 0, fdev)
                    try:
                        if fdev & Engine.E_READ:
                            client._handle_read()
                        else:
                            client._handle_error()
                    except EngineClientEOF:
                        self._debug("EngineClientEOF %s" % client)
                        if fdev & Engine.E_READ:
                            self.remove(client)
                        self._current_client = None
                        continue

                # or check for end of stream (do not handle both at the same
                # time because handle_read() may perform a partial read)
                elif event & select.EPOLLHUP:
                    self._debug(
                        "EPOLLHUP fd=%d %s (r%s,e%s,w%s)" %
                        (fd, client.__class__.__name__, client.fd_reader,
                         client.fd_error, client.fd_writer))
                    if fdev & Engine.E_READ:
                        if client._events & Engine.E_ERROR:
                            self.modify(client, 0, fdev)
                        else:
                            self.remove(client)
                    else:
                        if client._events & Engine.E_READ:
                            self.modify(client, 0, fdev)
                        else:
                            self.remove(client)

                # check for writing
                if event & select.EPOLLOUT:
                    self._debug(
                        "EPOLLOUT fd=%d %s (r%s,e%s,w%s)" %
                        (fd, client.__class__.__name__, client.fd_reader,
                         client.fd_error, client.fd_writer))
                    assert fdev == Engine.E_WRITE
                    assert client._events & fdev
                    self.modify(client, 0, fdev)
                    client._handle_write()

                self._current_client = None

                # apply any changes occured during processing
                if client.registered:
                    self.set_events(client, client._new_events)

            # check for task runloop timeout
            if timeout > 0 and time.time() >= start_time + timeout:
                raise EngineTimeoutException()

            # process clients timeout
            self.fire_timers()