def _call_select(space, iwtd_w, owtd_w, ewtd_w, ll_inl, ll_outl, ll_errl,
                 ll_timeval, timeout):
    fdlistin = fdlistout = fdlisterr = None
    nfds = -1
    if ll_inl:
        fdlistin, nfds = _build_fd_set(space, iwtd_w, ll_inl, nfds)
    if ll_outl:
        fdlistout, nfds = _build_fd_set(space, owtd_w, ll_outl, nfds)
    if ll_errl:
        fdlisterr, nfds = _build_fd_set(space, ewtd_w, ll_errl, nfds)

    if ll_timeval:
        end_time = timeutils.monotonic(space) + timeout
    else:
        end_time = 0.0

    while True:
        if ll_timeval:
            i = int(timeout)
            rffi.setintfield(ll_timeval, 'c_tv_sec', i)
            rffi.setintfield(ll_timeval, 'c_tv_usec',
                             int((timeout - i) * 1000000))

        res = _c.select(nfds + 1, ll_inl, ll_outl, ll_errl, ll_timeval)

        if res >= 0:
            break  # normal path
        err = _c.geterrno()
        if err != errno.EINTR:
            msg = _c.socket_strerror_unicode(err)
            raise OperationError(
                space.w_OSError,
                space.newtuple([space.newint(err),
                                space.newunicode(msg)]))
        # got EINTR, automatic retry
        space.getexecutioncontext().checksignals()
        if timeout > 0.0:
            timeout = end_time - timeutils.monotonic(space)
            if timeout < 0.0:
                timeout = 0.0

    resin_w = []
    resout_w = []
    reserr_w = []
    if res > 0:
        if fdlistin is not None:
            _unbuild_fd_set(space, iwtd_w, fdlistin, ll_inl, resin_w)
        if fdlistout is not None:
            _unbuild_fd_set(space, owtd_w, fdlistout, ll_outl, resout_w)
        if fdlisterr is not None:
            _unbuild_fd_set(space, ewtd_w, fdlisterr, ll_errl, reserr_w)
    return space.newtuple([
        space.newlist(resin_w),
        space.newlist(resout_w),
        space.newlist(reserr_w)
    ])
Example #2
0
    def poll(self, space, w_timeout):
        """
        Polls the set of registered file descriptors, returning a list containing
        any descriptors that have events or errors to report.

        the timeout parameter is in milliseconds"""
        if space.is_w(w_timeout, space.w_None):
            timeout = -1
            end_time = 0
        elif space.isinstance_w(w_timeout,
                                space.w_float) or space.isinstance_w(
                                    w_timeout, space.w_int):
            if space.is_true(space.lt(w_timeout, space.newint(0))):
                timeout = -1
                end_time = 0
            else:
                timeout = space.c_int_w(space.int(w_timeout))
                end_time = timeutils.monotonic(space) + timeout * 0.001
        else:
            raise oefmt(space.w_TypeError,
                        "timeout must be an integer or None")

        if self.running:
            raise oefmt(space.w_RuntimeError, "concurrent poll() invocation")
        while True:
            self.running = True
            try:
                retval = rpoll.poll(self.fddict, timeout)
            except rpoll.PollError as e:
                if e.errno == errno.EINTR:
                    space.getexecutioncontext().checksignals()
                    timeout = int(
                        (end_time - timeutils.monotonic(space)) * 1000.0 +
                        0.999)  # round up
                    if timeout < 0:
                        timeout = 0
                    continue
                message, lgt = e.get_msg_utf8()
                raise OperationError(
                    space.w_OSError,
                    space.newtuple(
                        [space.newint(e.errno),
                         space.newtext(message, lgt)]))
            finally:
                self.running = False
            break

        retval_w = []
        for fd, revents in retval:
            retval_w.append(
                space.newtuple([space.newint(fd),
                                space.newint(revents)]))
        return space.newlist(retval_w)
    def poll(self, space, w_timeout):
        """WARNING: the timeout parameter is in **milliseconds**!"""
        if space.is_w(w_timeout, space.w_None):
            timeout = -1
            end_time = 0
        else:
            # we want to be compatible with cpython and also accept things
            # that can be casted to integer (I think)
            try:
                # compute the integer
                w_timeout = space.int(w_timeout)
            except OperationError:
                raise oefmt(space.w_TypeError,
                            "timeout must be an integer or None")
            timeout = space.c_int_w(w_timeout)
            end_time = timeutils.monotonic(space) + timeout * 0.001

        if self.running:
            raise oefmt(space.w_RuntimeError, "concurrent poll() invocation")
        while True:
            self.running = True
            try:
                retval = rpoll.poll(self.fddict, timeout)
            except rpoll.PollError as e:
                if e.errno == errno.EINTR:
                    space.getexecutioncontext().checksignals()
                    timeout = int(
                        (end_time - timeutils.monotonic(space)) * 1000.0 +
                        0.999)  # round up
                    if timeout < 0:
                        timeout = 0
                    continue
                message = e.get_msg_unicode()
                raise OperationError(
                    space.w_OSError,
                    space.newtuple(
                        [space.newint(e.errno),
                         space.newunicode(message)]))
            finally:
                self.running = False
            break

        retval_w = []
        for fd, revents in retval:
            retval_w.append(
                space.newtuple([space.newint(fd),
                                space.newint(revents)]))
        return space.newlist(retval_w)
Example #4
0
    def descr_poll(self, space, timeout=-1.0, maxevents=-1):
        self.check_closed(space)
        if timeout < 0:
            end_time = 0.0
            itimeout = -1
        else:
            end_time = timeutils.monotonic(space) + timeout
            itimeout = int(timeout * 1000.0 + 0.999)

        if maxevents == -1:
            maxevents = FD_SETSIZE - 1
        elif maxevents < 1:
            raise oefmt(space.w_ValueError,
                        "maxevents must be greater than 0, not %d", maxevents)

        with lltype.scoped_alloc(rffi.CArray(epoll_event), maxevents) as evs:
            while True:
                nfds = epoll_wait(self.epfd, evs, maxevents, itimeout)
                if nfds < 0:
                    if get_saved_errno() == errno.EINTR:
                        space.getexecutioncontext().checksignals()
                        if itimeout >= 0:
                            timeout = end_time - timeutils.monotonic(space)
                            timeout = max(timeout, 0.0)
                            itimeout = int(timeout * 1000.0 + 0.999)
                        continue
                    raise exception_from_saved_errno(space, space.w_IOError)
                break

            elist_w = [None] * nfds
            for i in xrange(nfds):
                event = evs[i]
                elist_w[i] = space.newtuple(
                    [space.newint(event.c_data.c_fd), space.newint(event.c_events)]
                )
            return space.newlist(elist_w)
    def descr_control(self, space, w_changelist, max_events, w_timeout):

        self.check_closed(space)

        if max_events < 0:
            raise oefmt(space.w_ValueError,
                        "Length of eventlist must be 0 or positive, got %d",
                        max_events)

        if space.is_w(w_changelist, space.w_None):
            changelist_len = 0
        else:
            changelist_len = space.len_w(w_changelist)

        with lltype.scoped_alloc(rffi.CArray(kevent),
                                 changelist_len) as changelist:
            with lltype.scoped_alloc(rffi.CArray(kevent),
                                     max_events) as eventlist:
                with lltype.scoped_alloc(timespec) as timeout:

                    if not space.is_w(w_timeout, space.w_None):
                        _timeout = space.float_w(w_timeout)
                        if _timeout < 0:
                            raise oefmt(
                                space.w_ValueError,
                                "Timeout must be None or >= 0, got %s",
                                str(_timeout))
                        fill_timespec(_timeout, timeout)
                        timeout_at = timeutils.monotonic(space) + _timeout
                        ptimeout = timeout
                    else:
                        timeout_at = 0.0
                        ptimeout = lltype.nullptr(timespec)

                    if not space.is_w(w_changelist, space.w_None):
                        i = 0
                        for w_ev in space.listview(w_changelist):
                            ev = space.interp_w(W_Kevent, w_ev)
                            changelist[i].c_ident = ev.ident
                            changelist[i].c_filter = ev.filter
                            changelist[i].c_flags = ev.flags
                            changelist[i].c_fflags = ev.fflags
                            changelist[i].c_data = ev.data
                            changelist[i].c_udata = ev.udata
                            i += 1
                        pchangelist = changelist
                    else:
                        pchangelist = lltype.nullptr(rffi.CArray(kevent))

                    while True:
                        nfds = syscall_kevent(self.kqfd, pchangelist,
                                              changelist_len, eventlist,
                                              max_events, ptimeout)
                        if nfds >= 0:
                            break
                        if rposix.get_saved_errno() != errno.EINTR:
                            raise exception_from_saved_errno(
                                space, space.w_OSError)
                        space.getexecutioncontext().checksignals()
                        if ptimeout:
                            _timeout = (timeout_at -
                                        timeutils.monotonic(space))
                            if _timeout < 0.0:
                                _timeout = 0.0
                            fill_timespec(_timeout, ptimeout)

                    elist_w = [None] * nfds
                    for i in xrange(nfds):

                        evt = eventlist[i]

                        w_event = W_Kevent(space)
                        w_event.ident = evt.c_ident
                        w_event.filter = evt.c_filter
                        w_event.flags = evt.c_flags
                        w_event.fflags = evt.c_fflags
                        w_event.data = evt.c_data
                        w_event.udata = evt.c_udata

                        elist_w[i] = w_event

                    return space.newlist(elist_w)