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) ])
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)
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)