def _select(self, for_writing): """Returns 0 when reading/writing is possible, 1 when timing out and -1 on error.""" timeout = self.timeout if timeout <= 0.0 or self.fd == _c.INVALID_SOCKET: # blocking I/O or no socket. return 0 tv = rffi.make(_c.timeval) rffi.setintfield(tv, 'c_tv_sec', int(timeout)) rffi.setintfield(tv, 'c_tv_usec', int((timeout - int(timeout)) * 1000000)) fds = rffi.make(_c.fd_set) rffi.setintfield(fds, 'c_fd_count', 1) fds.c_fd_array[0] = rffi.cast(_c.socketfd_type, self.fd) null = lltype.nullptr(_c.fd_set) if for_writing: n = _c.select(self.fd + 1, null, fds, null, tv) else: n = _c.select(self.fd + 1, fds, null, null, tv) lltype.free(fds, flavor='raw') lltype.free(tv, flavor='raw') if n < 0: return -1 if n == 0: return 1 return 0
def _select(self, for_writing): """Returns 0 when reading/writing is possible, 1 when timing out and -1 on error.""" timeout = self.timeout if timeout <= 0.0 or self.fd == _c.INVALID_SOCKET: # blocking I/O or no socket. return 0 tv = rffi.make(_c.timeval) rffi.setintfield(tv, 'c_tv_sec', int(timeout)) rffi.setintfield(tv, 'c_tv_usec', int((timeout-int(timeout)) * 1000000)) fds = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(fds) _c.FD_SET(self.fd, fds) null = lltype.nullptr(_c.fd_set.TO) if for_writing: n = _c.select(self.fd + 1, null, fds, null, tv) else: n = _c.select(self.fd + 1, fds, null, null, tv) lltype.free(fds, flavor='raw') lltype.free(tv, flavor='raw') if n < 0: return -1 if n == 0: return 1 return 0
def select(inl, outl, excl, timeout=-1.0): nfds = 0 if inl: ll_inl = lltype.malloc(_c.fd_set.TO, flavor="raw") _c.FD_ZERO(ll_inl) for i in inl: _c.FD_SET(i, ll_inl) if i > nfds: nfds = i else: ll_inl = lltype.nullptr(_c.fd_set.TO) if outl: ll_outl = lltype.malloc(_c.fd_set.TO, flavor="raw") _c.FD_ZERO(ll_outl) for i in outl: _c.FD_SET(i, ll_outl) if i > nfds: nfds = i else: ll_outl = lltype.nullptr(_c.fd_set.TO) if excl: ll_excl = lltype.malloc(_c.fd_set.TO, flavor="raw") _c.FD_ZERO(ll_excl) for i in excl: _c.FD_SET(i, ll_excl) if i > nfds: nfds = i else: ll_excl = lltype.nullptr(_c.fd_set.TO) if timeout != -1.0: ll_timeval = lltype.malloc(_c.timeval, flavor="raw") frac = math.fmod(timeout, 1.0) ll_timeval.c_tv_sec = int(timeout) ll_timeval.c_tv_usec = int((timeout - int(timeout)) * 1000000.0) else: ll_timeval = lltype.nullptr(_c.timeval) try: res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if res == -1: raise SelectError(_c.geterrno()) if res == 0: return ([], [], []) else: return ( [i for i in inl if _c.FD_ISSET(i, ll_inl)], [i for i in outl if _c.FD_ISSET(i, ll_outl)], [i for i in excl if _c.FD_ISSET(i, ll_excl)], ) finally: if ll_inl: lltype.free(ll_inl, flavor="raw") if ll_outl: lltype.free(ll_outl, flavor="raw") if ll_excl: lltype.free(ll_excl, flavor="raw") if ll_timeval: lltype.free(ll_timeval, flavor="raw")
def select(inl, outl, excl, timeout=-1.0): nfds = 0 if inl: ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_inl) for i in inl: _c.FD_SET(i, ll_inl) if i > nfds: nfds = i else: ll_inl = lltype.nullptr(_c.fd_set.TO) if outl: ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_outl) for i in outl: _c.FD_SET(i, ll_outl) if i > nfds: nfds = i else: ll_outl = lltype.nullptr(_c.fd_set.TO) if excl: ll_excl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_excl) for i in excl: _c.FD_SET(i, ll_excl) if i > nfds: nfds = i else: ll_excl = lltype.nullptr(_c.fd_set.TO) if timeout != -1.0: ll_timeval = rffi.make(_c.timeval) rffi.setintfield(ll_timeval, 'c_tv_sec', int(timeout)) rffi.setintfield(ll_timeval, 'c_tv_usec', int((timeout-int(timeout)) * 1000000)) else: ll_timeval = lltype.nullptr(_c.timeval) try: res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if res == -1: raise SelectError(_c.geterrno()) if res == 0: return ([], [], []) else: return ( [i for i in inl if _c.FD_ISSET(i, ll_inl)], [i for i in outl if _c.FD_ISSET(i, ll_outl)], [i for i in excl if _c.FD_ISSET(i, ll_excl)]) finally: if ll_inl: lltype.free(ll_inl, flavor='raw') if ll_outl: lltype.free(ll_outl, flavor='raw') if ll_excl: lltype.free(ll_excl, flavor='raw') if ll_timeval: lltype.free(ll_timeval, flavor='raw')
def _connect(self, address): """Connect the socket to a remote address.""" addr = address.lock() res = _c.socketconnect(self.fd, addr, address.addrlen) address.unlock() errno = _c.geterrno() timeout = self.timeout if timeout > 0.0 and res < 0 and errno == _c.EWOULDBLOCK: tv = rffi.make(_c.timeval) rffi.setintfield(tv, 'c_tv_sec', int(timeout)) rffi.setintfield(tv, 'c_tv_usec', int((timeout-int(timeout)) * 1000000)) fds = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(fds) _c.FD_SET(self.fd, fds) fds_exc = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(fds_exc) _c.FD_SET(self.fd, fds_exc) null = lltype.nullptr(_c.fd_set.TO) try: n = _c.select(self.fd + 1, null, fds, fds_exc, tv) if n > 0: if _c.FD_ISSET(self.fd, fds): # socket writable == connected return (0, False) else: # per MS docs, call getsockopt() to get error assert _c.FD_ISSET(self.fd, fds_exc) return (self.getsockopt_int(_c.SOL_SOCKET, _c.SO_ERROR), False) elif n == 0: return (_c.EWOULDBLOCK, True) else: return (_c.geterrno(), False) finally: lltype.free(fds, flavor='raw') lltype.free(fds_exc, flavor='raw') lltype.free(tv, flavor='raw') if res == 0: errno = 0 return (errno, False)
def _connect(self, address): """Connect the socket to a remote address.""" addr = address.lock() res = _c.socketconnect(self.fd, addr, address.addrlen) address.unlock() errno = _c.geterrno() timeout = self.timeout if timeout > 0.0 and res < 0 and errno == _c.EWOULDBLOCK: tv = rffi.make(_c.timeval) rffi.setintfield(tv, 'c_tv_sec', int(timeout)) rffi.setintfield(tv, 'c_tv_usec', int((timeout - int(timeout)) * 1000000)) fds = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(fds) _c.FD_SET(self.fd, fds) fds_exc = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(fds_exc) _c.FD_SET(self.fd, fds_exc) null = lltype.nullptr(_c.fd_set.TO) try: n = _c.select(self.fd + 1, null, fds, fds_exc, tv) if n > 0: if _c.FD_ISSET(self.fd, fds): # socket writable == connected return (0, False) else: # per MS docs, call getsockopt() to get error assert _c.FD_ISSET(self.fd, fds_exc) return (self.getsockopt_int( _c.SOL_SOCKET, _c.SO_ERROR), False) elif n == 0: return (_c.EWOULDBLOCK, True) else: return (_c.geterrno(), False) finally: lltype.free(fds, flavor='raw') lltype.free(fds_exc, flavor='raw') lltype.free(tv, flavor='raw') if res == 0: errno = 0 return (errno, False)
def select(space, w_iwtd, w_owtd, w_ewtd, w_timeout=None): """Wait until one or more file descriptors are ready for some kind of I/O. The first three arguments are sequences of file descriptors to be waited for: rlist -- wait until ready for reading wlist -- wait until ready for writing xlist -- wait for an ``exceptional condition'' If only one kind of condition is required, pass [] for the other lists. A file descriptor is either a socket or file object, or a small integer gotten from a fileno() method call on one of those. The optional 4th argument specifies a timeout in seconds; it may be a floating point number to specify fractions of seconds. If it is absent or None, the call will never time out. The return value is a tuple of three lists corresponding to the first three arguments; each contains the subset of the corresponding file descriptors that are ready. *** IMPORTANT NOTICE *** On Windows, only sockets are supported; on Unix, all file descriptors. """ iwtd_w = space.listview(w_iwtd) owtd_w = space.listview(w_owtd) ewtd_w = space.listview(w_ewtd) ll_inl = lltype.nullptr(_c.fd_set.TO) ll_outl = lltype.nullptr(_c.fd_set.TO) ll_errl = lltype.nullptr(_c.fd_set.TO) ll_timeval = lltype.nullptr(_c.timeval) try: fdlistin = None fdlistout = None fdlisterr = None nfds = -1 if len(iwtd_w) > 0: ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw') fdlistin, nfds = _build_fd_set(space, iwtd_w, ll_inl, nfds) if len(owtd_w) > 0: ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw') fdlistout, nfds = _build_fd_set(space, owtd_w, ll_outl, nfds) if len(ewtd_w) > 0: ll_errl = lltype.malloc(_c.fd_set.TO, flavor='raw') fdlisterr, nfds = _build_fd_set(space, ewtd_w, ll_errl, nfds) if space.is_w(w_timeout, space.w_None): timeout = -1.0 else: timeout = space.float_w(w_timeout) if timeout >= 0.0: ll_timeval = rffi.make(_c.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: errno = _c.geterrno() msg = _c.socket_strerror_str(errno) w_errortype = space.fromcache(Cache).w_error raise OperationError(w_errortype, space.newtuple([ space.wrap(errno), space.wrap(msg)])) 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) finally: if ll_timeval: lltype.free(ll_timeval, flavor='raw') if ll_errl: lltype.free(ll_errl, flavor='raw') if ll_outl: lltype.free(ll_outl, flavor='raw') if ll_inl: lltype.free(ll_inl, flavor='raw') return space.newtuple([space.newlist(resin_w), space.newlist(resout_w), space.newlist(reserr_w)])