Example #1
0
        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()
            if self.timeout > 0.0 and res < 0 and errno == _c.EINPROGRESS:
                timeout = self._select(True)
                errno = _c.geterrno()
                if timeout == 0:
                    addr = address.lock()
                    res = _c.socketconnect(self.fd, addr, address.addrlen)
                    address.unlock()
                    if res < 0:
                        errno = _c.geterrno()
                        if errno == _c.EISCONN:
                            res = 0
                elif timeout == -1:
                    return (errno, False)
                else:
                    return (_c.EWOULDBLOCK, True)

            if res == 0:
                errno = 0
            return (errno, False)
Example #2
0
        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()
            if self.timeout > 0.0 and res < 0 and errno == _c.EINPROGRESS:
                timeout = self._select(True)
                errno = _c.geterrno()
                if timeout == 0:
                    addr = address.lock()
                    res = _c.socketconnect(self.fd, addr, address.addrlen)
                    address.unlock()
                    if res < 0:
                        errno = _c.geterrno()
                        if errno == _c.EISCONN:
                            res = 0
                elif timeout == -1:
                    return (errno, False)
                else:
                    return (_c.EWOULDBLOCK, True)

            if res == 0:
                errno = 0
            return (errno, False)
Example #3
0
        def WRITE(self, data):
            from pypy.rlib._rsocket_rffi import send, geterrno

            length = send(self.fd, data, len(data), 0)
            if length < 0:
                raise WindowsError(geterrno(), "send")
            return length
Example #4
0
    def poll(fddict, timeout=-1):
        """'fddict' maps file descriptors to interesting events.
        'timeout' is an integer in milliseconds, and NOT a float
        number of seconds, but it's the same in CPython.  Use -1 for infinite.
        Returns a list [(fd, events)].
        """
        numfd = len(fddict)
        pollfds = lltype.malloc(_c.pollfdarray, numfd, flavor='raw')
        try:
            i = 0
            for fd, events in fddict.iteritems():
                rffi.setintfield(pollfds[i], 'c_fd', fd)
                rffi.setintfield(pollfds[i], 'c_events', events)
                i += 1
            assert i == numfd

            ret = _c.poll(pollfds, numfd, timeout)

            if ret < 0:
                raise PollError(_c.geterrno())

            retval = []
            for i in range(numfd):
                pollfd = pollfds[i]
                fd      = rffi.cast(lltype.Signed, pollfd.c_fd)
                revents = rffi.cast(lltype.Signed, pollfd.c_revents)
                if revents:
                    retval.append((fd, revents))
        finally:
            lltype.free(pollfds, flavor='raw')
        return retval
Example #5
0
 def READ(self, size):
     from pypy.rlib._rsocket_rffi import socketrecv, geterrno
     with rffi.scoped_alloc_buffer(size) as buf:
         length = socketrecv(self.fd, buf.raw, buf.size, 0)
         if length < 0:
             raise WindowsError(geterrno(), "recv")
         return buf.str(length)
Example #6
0
    def poll(fddict, timeout=-1):
        """'fddict' maps file descriptors to interesting events.
        'timeout' is an integer in milliseconds, and NOT a float
        number of seconds, but it's the same in CPython.  Use -1 for infinite.
        Returns a list [(fd, events)].
        """
        numfd = len(fddict)
        pollfds = lltype.malloc(_c.pollfdarray, numfd, flavor='raw')
        try:
            i = 0
            for fd, events in fddict.iteritems():
                rffi.setintfield(pollfds[i], 'c_fd', fd)
                rffi.setintfield(pollfds[i], 'c_events', events)
                i += 1
            assert i == numfd

            ret = _c.poll(pollfds, numfd, timeout)

            if ret < 0:
                raise PollError(_c.geterrno())

            retval = []
            for i in range(numfd):
                pollfd = pollfds[i]
                fd = rffi.cast(lltype.Signed, pollfd.c_fd)
                revents = rffi.cast(lltype.Signed, pollfd.c_revents)
                if revents:
                    retval.append((fd, revents))
        finally:
            lltype.free(pollfds, flavor='raw')
        return retval
Example #7
0
 def READ(self, size):
     from pypy.rlib._rsocket_rffi import socketrecv, geterrno
     with rffi.scoped_alloc_buffer(size) as buf:
         length = socketrecv(self.fd, buf.raw, buf.size, 0)
         if length < 0:
             raise WindowsError(geterrno(), "recv")
         return buf.str(length)
Example #8
0
        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)
Example #9
0
        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)
Example #10
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")
Example #11
0
File: rpoll.py Project: njues/Sypy
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')
Example #12
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 = 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')
Example #13
0
    def connect_ex(self, address):
        """This is like connect(address), but returns an error code (the errno
        value) instead of raising an exception when an error occurs."""
        addr = address.lock()
        res = _c.socketconnect(self.fd, addr, address.addrlen)
        address.unlock()
        if self.timeout > 0.0:
            errno = _c.geterrno()
            if res < 0 and errno == _c.EINPROGRESS:
                timeout = self._select(True)
                if timeout == 0:
                    addr = address.lock()
                    res = _c.socketconnect(self.fd, addr, address.addrlen)
                    address.unlock()
                elif timeout == -1:
                    return _c.geterrno()
                else:
                    return _c.EWOULDBLOCK

        if res != 0:
            return _c.geterrno()
        return res
Example #14
0
 def connect_ex(self, address):
     """This is like connect(address), but returns an error code (the errno
     value) instead of raising an exception when an error occurs."""
     addr = address.lock()
     res = _c.socketconnect(self.fd, addr, address.addrlen)
     address.unlock()
     if self.timeout > 0.0:
         errno = _c.geterrno()
         if res < 0 and errno == _c.EINPROGRESS:
             timeout = self._select(True)
             if timeout == 0:
                 addr = address.lock()
                 res = _c.socketconnect(self.fd, addr, address.addrlen)
                 address.unlock()
             elif timeout == -1:
                 return _c.geterrno()
             else:
                 return _c.EWOULDBLOCK
             
     if res != 0:
         return _c.geterrno()
     return res
Example #15
0
    def connect(self, address):
        """Connect the socket to a remote address."""
        addr = address.lock()
        res = _c.socketconnect(self.fd, addr, address.addrlen)
        address.unlock()
        if self.timeout > 0.0:
            errno = _c.geterrno()
            if res < 0 and errno == _c.EINPROGRESS:
                timeout = self._select(True)
                if timeout == 0:
                    addr = address.lock()
                    res = _c.socketconnect(self.fd, addr, address.addrlen)
                    address.unlock()
                elif timeout == -1:
                    raise self.error_handler()
                else:
                    raise SocketTimeout

        if res != 0:
            raise self.error_handler()
Example #16
0
 def connect(self, address):
     """Connect the socket to a remote address."""
     addr = address.lock()
     res = _c.socketconnect(self.fd, addr, address.addrlen)
     address.unlock()
     if self.timeout > 0.0:
         errno = _c.geterrno()
         if res < 0 and errno == _c.EINPROGRESS:
             timeout = self._select(True)
             if timeout == 0:
                 addr = address.lock()
                 res = _c.socketconnect(self.fd, addr, address.addrlen)
                 address.unlock()
             elif timeout == -1:
                 raise self.error_handler()
             else:
                 raise SocketTimeout
             
     if res != 0:
         raise self.error_handler()
Example #17
0
    def poll(fddict, timeout=-1):
        """'fddict' maps file descriptors to interesting events.
        'timeout' is an integer in milliseconds, and NOT a float
        number of seconds, but it's the same in CPython.  Use -1 for infinite.
        Returns a list [(fd, events)].
        """
        numfd = len(fddict)
        numevents = 0
        socketevents = lltype.malloc(_c.WSAEVENT_ARRAY, numfd, flavor='raw')
        try:
            eventdict = {}

            for fd, events in fddict.iteritems():
                # select desired events
                wsaEvents = 0
                if events & _c.POLLIN:
                    wsaEvents |= _c.FD_READ | _c.FD_ACCEPT | _c.FD_CLOSE
                if events & _c.POLLOUT:
                    wsaEvents |= _c.FD_WRITE | _c.FD_CONNECT | _c.FD_CLOSE

                # if no events then ignore socket
                if wsaEvents == 0:
                    continue

                # select socket for desired events
                event = _c.WSACreateEvent()
                _c.WSAEventSelect(fd, event, wsaEvents)

                eventdict[fd] = event
                socketevents[numevents] = event
                numevents += 1

            assert numevents <= numfd

            # if no sockets then return immediately
            # XXX commented out by arigo - we just want to sleep for
            #     'timeout' milliseconds in this case, which is what
            #     I hope WSAWaitForMultipleEvents will do, no?
            #if numevents == 0:
            #    return []

            # prepare timeout
            if timeout < 0:
                timeout = _c.INFINITE

            ret = _c.WSAWaitForMultipleEvents(numevents, socketevents, False,
                                              timeout, False)

            if ret == _c.WSA_WAIT_TIMEOUT:
                return []

            if ret == _c.WSA_WAIT_FAILED:
                raise PollError(_c.geterrno())

            retval = []
            info = rffi.make(_c.WSANETWORKEVENTS)
            for fd, event in eventdict.iteritems():
                if _c.WSAEnumNetworkEvents(fd, event, info) < 0:
                    continue
                revents = 0
                if info.c_lNetworkEvents & _c.FD_READ:
                    revents |= _c.POLLIN
                if info.c_lNetworkEvents & _c.FD_ACCEPT:
                    revents |= _c.POLLIN
                if info.c_lNetworkEvents & _c.FD_WRITE:
                    revents |= _c.POLLOUT
                if info.c_lNetworkEvents & _c.FD_CONNECT:
                    if info.c_iErrorCode[_c.FD_CONNECT_BIT]:
                        revents |= _c.POLLERR
                    else:
                        revents |= _c.POLLOUT
                if info.c_lNetworkEvents & _c.FD_CLOSE:
                    if info.c_iErrorCode[_c.FD_CLOSE_BIT]:
                        revents |= _c.POLLERR
                    else:
                        if fddict[fd] & _c.POLLIN:
                            revents |= _c.POLLIN
                        if fddict[fd] & _c.POLLOUT:
                            revents |= _c.POLLOUT
                if revents:
                    retval.append((fd, revents))

            lltype.free(info, flavor='raw')

        finally:
            for i in range(numevents):
                _c.WSACloseEvent(socketevents[i])
            lltype.free(socketevents, flavor='raw')

        return retval
Example #18
0
def last_error():
    return CSocketError(_c.geterrno())
Example #19
0
def last_error():
    return CSocketError(_c.geterrno())
Example #20
0
 def WRITE(self, data):
     from pypy.rlib._rsocket_rffi import send, geterrno
     length = send(self.fd, data, len(data), 0)
     if length < 0:
         raise WindowsError(geterrno(), "send")
     return length
Example #21
0
    def poll(fddict, timeout=-1):
        """'fddict' maps file descriptors to interesting events.
        'timeout' is an integer in milliseconds, and NOT a float
        number of seconds, but it's the same in CPython.  Use -1 for infinite.
        Returns a list [(fd, events)].
        """
        numfd = len(fddict)
        numevents = 0
        socketevents = lltype.malloc(_c.WSAEVENT_ARRAY, numfd, flavor='raw')
        try:
            eventdict = {}

            for fd, events in fddict.iteritems():
                # select desired events
                wsaEvents = 0
                if events & _c.POLLIN:
                    wsaEvents |= _c.FD_READ | _c.FD_ACCEPT | _c.FD_CLOSE
                if events & _c.POLLOUT:
                    wsaEvents |= _c.FD_WRITE | _c.FD_CONNECT | _c.FD_CLOSE

                # if no events then ignore socket
                if wsaEvents == 0:
                    continue

                # select socket for desired events
                event = _c.WSACreateEvent()
                if _c.WSAEventSelect(fd, event, wsaEvents) != 0:
                    raise PollError(_c.geterrno())

                eventdict[fd] = event
                socketevents[numevents] = event
                numevents += 1

            assert numevents <= numfd

            # if no sockets then return immediately
            # XXX commented out by arigo - we just want to sleep for
            #     'timeout' milliseconds in this case, which is what
            #     I hope WSAWaitForMultipleEvents will do, no?
            #if numevents == 0:
            #    return []

            # prepare timeout
            if timeout < 0:
                timeout = _c.INFINITE

            ret = _c.WSAWaitForMultipleEvents(numevents, socketevents,
                                              False, timeout, False)

            if ret == _c.WSA_WAIT_TIMEOUT:
                return []

            if ret == r_uint(_c.WSA_WAIT_FAILED):
                raise PollError(_c.geterrno())

            retval = []
            info = rffi.make(_c.WSANETWORKEVENTS)
            for fd, event in eventdict.iteritems():
                if _c.WSAEnumNetworkEvents(fd, event, info) < 0:
                    continue
                revents = 0
                if info.c_lNetworkEvents & _c.FD_READ:
                    revents |= _c.POLLIN
                if info.c_lNetworkEvents & _c.FD_ACCEPT:
                    revents |= _c.POLLIN
                if info.c_lNetworkEvents & _c.FD_WRITE:
                    revents |= _c.POLLOUT
                if info.c_lNetworkEvents & _c.FD_CONNECT:
                    if info.c_iErrorCode[_c.FD_CONNECT_BIT]:
                        revents |= _c.POLLERR
                    else:
                        revents |= _c.POLLOUT
                if info.c_lNetworkEvents & _c.FD_CLOSE:
                    if info.c_iErrorCode[_c.FD_CLOSE_BIT]:
                        revents |= _c.POLLERR
                    else:
                        if fddict[fd] & _c.POLLIN:
                            revents |= _c.POLLIN
                        if fddict[fd] & _c.POLLOUT:
                            revents |= _c.POLLOUT
                if revents:
                    retval.append((fd, revents))

            lltype.free(info, flavor='raw')

        finally:
            for fd, event in eventdict.iteritems():
                _c.WSAEventSelect(fd, event, 0)
                _c.WSACloseEvent(event)
            lltype.free(socketevents, flavor='raw')

        return retval
Example #22
0
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)])