New test.
[mono.git] / mono / io-layer / sockets.c
index 2089557cc8d39e8d13e25baa6a7e5b0aa9e2a104..5659c69762297e1ea261ed68f33525101cf5f8e6 100644 (file)
 #undef DEBUG
 
 static guint32 startup_count=0;
-static GPtrArray *sockets=NULL;
 static pthread_key_t error_key;
 static mono_once_t error_key_once=MONO_ONCE_INIT;
 
-static void socket_close_private (gpointer handle);
+static void socket_close (gpointer handle, gpointer data);
 
 struct _WapiHandleOps _wapi_socket_ops = {
-       NULL,                   /* close_shared */
-       socket_close_private,   /* close_private */
+       socket_close,           /* close */
        NULL,                   /* signal */
        NULL,                   /* own */
        NULL,                   /* is_owned */
+       NULL,                   /* special_wait */
+       NULL                    /* prewait */
 };
 
 static mono_once_t socket_ops_once=MONO_ONCE_INIT;
@@ -58,105 +58,82 @@ static void socket_ops_init (void)
        /* No capabilities to register */
 }
 
-static void socket_close_private (gpointer handle)
+static void socket_close (gpointer handle, gpointer data G_GNUC_UNUSED)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
        int ret;
 
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": closing socket handle %p",
-                 handle);
+       g_message ("%s: closing socket handle %p", __func__, handle);
 #endif
 
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return;
        }
 
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle %p", handle);
-               WSASetLastError(WSAENOTSOCK);
-               return;
-       }
-
-       g_ptr_array_remove_fast(sockets, GUINT_TO_POINTER (handle));
-
-       ret=close(socket_private_handle->fd);
-       if(ret==-1) {
+       do {
+               ret = close (GPOINTER_TO_UINT(handle));
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending ());
+       
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": close error: %s",
-                         strerror(errno));
+               g_message ("%s: close error: %s", __func__, strerror (errno));
 #endif
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
-
-               return;
        }
 }
 
 int WSAStartup(guint32 requested, WapiWSAData *data)
 {
-       if(data==NULL) {
+       if (data == NULL) {
                return(WSAEFAULT);
        }
 
        /* Insist on v2.0+ */
-       if(requested < MAKEWORD(2,0)) {
+       if (requested < MAKEWORD(2,0)) {
                return(WSAVERNOTSUPPORTED);
        }
 
-       if(startup_count==0) {
-               sockets=g_ptr_array_new();
-       }
-       
        startup_count++;
 
        /* I've no idea what is the minor version of the spec I read */
-       data->wHighVersion=MAKEWORD(2,0);
+       data->wHighVersion = MAKEWORD(2,2);
        
-       data->wVersion=requested < data->wHighVersion? requested:
+       data->wVersion = requested < data->wHighVersion? requested:
                data->wHighVersion;
 
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": high version 0x%x",
-                 data->wHighVersion);
+       g_message ("%s: high version 0x%x", __func__, data->wHighVersion);
 #endif
        
-       strncpy(data->szDescription, "WAPI", WSADESCRIPTION_LEN);
-       strncpy(data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
+       strncpy (data->szDescription, "WAPI", WSADESCRIPTION_LEN);
+       strncpy (data->szSystemStatus, "groovy", WSASYS_STATUS_LEN);
        
        return(0);
 }
 
+static gboolean
+cleanup_close (gpointer handle, gpointer data)
+{
+       _wapi_handle_ops_close (handle, NULL);
+       return TRUE;
+}
+
 int WSACleanup(void)
 {
-       guint32 i;
-       
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION ": cleaning up");
+       g_message ("%s: cleaning up", __func__);
 #endif
 
-       if(--startup_count) {
+       if (--startup_count) {
                /* Do nothing */
                return(0);
        }
-       
-       /* Close down all sockets */
-       for(i=0; i<sockets->len; i++) {
-               gpointer handle;
-
-               handle=g_ptr_array_index(sockets, i);
-               _wapi_handle_ops_close_private (handle);
-       }
 
-       g_ptr_array_free(sockets, FALSE);
-       sockets=NULL;
-       
+       _wapi_handle_foreach (WAPI_HANDLE_SOCKET, cleanup_close, NULL);
        return(0);
 }
 
@@ -164,7 +141,7 @@ static void error_init(void)
 {
        int ret;
        
-       ret = pthread_key_create(&error_key, NULL);
+       ret = pthread_key_create (&error_key, NULL);
        g_assert (ret == 0);
 }
 
@@ -172,8 +149,8 @@ void WSASetLastError(int error)
 {
        int ret;
        
-       mono_once(&error_key_once, error_init);
-       ret = pthread_setspecific(error_key, GINT_TO_POINTER(error));
+       mono_once (&error_key_once, error_init);
+       ret = pthread_setspecific (error_key, GINT_TO_POINTER(error));
        g_assert (ret == 0);
 }
 
@@ -182,123 +159,108 @@ int WSAGetLastError(void)
        int err;
        void *errptr;
        
-       mono_once(&error_key_once, error_init);
-       errptr=pthread_getspecific(error_key);
-       err=GPOINTER_TO_INT(errptr);
+       mono_once (&error_key_once, error_init);
+       errptr = pthread_getspecific (error_key);
+       err = GPOINTER_TO_INT(errptr);
        
        return(err);
 }
 
-int closesocket(guint32 handle)
+int closesocket(guint32 fd)
 {
-       _wapi_handle_unref (GUINT_TO_POINTER (handle));
+       gpointer handle = GUINT_TO_POINTER (fd);
+       
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
+               return(0);
+       }
+       
+       _wapi_handle_unref (handle);
        return(0);
 }
 
-guint32 _wapi_accept(guint32 handle, struct sockaddr *addr,
-                    socklen_t *addrlen)
+guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       struct _WapiHandlePrivate_socket *new_socket_private_handle;
+       gpointer handle = GUINT_TO_POINTER (fd);
        gpointer new_handle;
-       gboolean ok;
-       int fd;
-       int thr_ret;
-       guint32 ret = INVALID_SOCKET;
+       int new_fd;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(INVALID_SOCKET);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(INVALID_SOCKET);
        }
        
-       fd=accept(socket_private_handle->fd, addr, addrlen);
-       if(fd==-1) {
+       do {
+               new_fd = accept (fd, addr, addrlen);
+       } while (new_fd == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending());
+
+       if (new_fd == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": accept error: %s",
-                         strerror(errno));
+               g_message ("%s: accept error: %s", __func__, strerror(errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(INVALID_SOCKET);
        }
 
-       new_handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
-       if(new_handle==_WAPI_HANDLE_INVALID) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error creating socket handle");
+       if (new_fd >= _wapi_fd_reserve) {
+#ifdef DEBUG
+               g_message ("%s: File descriptor is too big", __func__);
+#endif
+
+               WSASetLastError (WSASYSCALLFAILURE);
+               
+               close (new_fd);
+               
+               return(INVALID_SOCKET);
+       }
+
+       new_handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, new_fd, NULL);
+       if(new_handle == _WAPI_HANDLE_INVALID) {
+               g_warning ("%s: error creating socket handle", __func__);
+               WSASetLastError (ERROR_GEN_FAILURE);
                return(INVALID_SOCKET);
        }
 
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             new_handle);
-       thr_ret = _wapi_handle_lock_handle (new_handle);
-       g_assert (thr_ret == 0);
-       
-       ok=_wapi_lookup_handle (new_handle, WAPI_HANDLE_SOCKET, NULL,
-                               (gpointer *)&new_socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               goto cleanup;
-       }
-       ret = GPOINTER_TO_UINT (new_handle);
-       
-       new_socket_private_handle->fd=fd;
-       
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": returning newly accepted socket handle %p with fd %d",
-                 new_handle, new_socket_private_handle->fd);
+       g_message ("%s: returning newly accepted socket handle %p with",
+                  __func__, new_handle);
 #endif
-
-cleanup:
-       thr_ret = _wapi_handle_unlock_handle (new_handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
        
-       return(ret);
+       return(new_fd);
 }
 
-int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen)
+int _wapi_bind(guint32 fd, struct sockaddr *my_addr, socklen_t addrlen)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
-       
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
        
-       ret=bind(socket_private_handle->fd, my_addr, addrlen);
-       if(ret==-1) {
+       ret = bind (fd, my_addr, addrlen);
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": bind error: %s",
-                         strerror(errno));
+               g_message ("%s: bind error: %s", __func__, strerror(errno));
 #endif
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -306,30 +268,28 @@ int _wapi_bind(guint32 handle, struct sockaddr *my_addr, socklen_t addrlen)
        return(ret);
 }
 
-int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr,
+int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr,
                  socklen_t addrlen)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        gint errnum;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
        
-       ret=connect(socket_private_handle->fd, serv_addr, addrlen);
-       if(ret==-1 && errno==EACCES) {
+       do {
+               ret = connect (fd, serv_addr, addrlen);
+       } while (ret==-1 && errno==EINTR && !_wapi_thread_cur_apc_pending());
+
+       if (ret == -1 && errno == EACCES) {
                /* Try setting SO_BROADCAST and connecting again, but
                 * keep the original errno
                 */
@@ -337,22 +297,27 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr,
                
                errnum = errno;
 
-               ret=setsockopt (socket_private_handle->fd, SOL_SOCKET,
-                               SO_BROADCAST, &true, sizeof(true));
-               if(ret==0) {
-                       ret=connect (socket_private_handle->fd, serv_addr,
-                                    addrlen);
+               ret = setsockopt (fd, SOL_SOCKET, SO_BROADCAST, &true,
+                                 sizeof(true));
+               if (ret == 0) {
+                       do {
+                               ret = connect (fd, serv_addr, addrlen);
+                       } while (ret==-1 && errno==EINTR &&
+                                !_wapi_thread_cur_apc_pending());
                }
-       } else if (ret==-1) {
+       } else if (ret == -1) {
                errnum = errno;
        }
        
-       if(ret==-1) {
+       if (ret == -1) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": connect error: %s",
-                         strerror(errnum));
+               g_message ("%s: connect error: %s", __func__,
+                          strerror (errnum));
 #endif
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
+               if (errnum == WSAEINPROGRESS)
+                       errnum = WSAEWOULDBLOCK; /* see bug #73053 */
+
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -360,36 +325,30 @@ int _wapi_connect(guint32 handle, const struct sockaddr *serv_addr,
        return(ret);
 }
 
-int _wapi_getpeername(guint32 handle, struct sockaddr *name,
-                     socklen_t *namelen)
+int _wapi_getpeername(guint32 fd, struct sockaddr *name, socklen_t *namelen)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
 
-       ret=getpeername(socket_private_handle->fd, name, namelen);
-       if(ret==-1) {
+       ret = getpeername (fd, name, namelen);
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": getpeername error: %s",
-                         strerror(errno));
+               g_message ("%s: getpeername error: %s", __func__,
+                          strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
 
                return(SOCKET_ERROR);
@@ -398,36 +357,30 @@ int _wapi_getpeername(guint32 handle, struct sockaddr *name,
        return(ret);
 }
 
-int _wapi_getsockname(guint32 handle, struct sockaddr *name,
-                     socklen_t *namelen)
+int _wapi_getsockname(guint32 fd, struct sockaddr *name, socklen_t *namelen)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
 
-       ret=getsockname(socket_private_handle->fd, name, namelen);
-       if(ret==-1) {
+       ret = getsockname (fd, name, namelen);
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": getsockname error: %s",
-                         strerror(errno));
+               g_message ("%s: getsockname error: %s", __func__,
+                          strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
 
                return(SOCKET_ERROR);
@@ -436,74 +389,82 @@ int _wapi_getsockname(guint32 handle, struct sockaddr *name,
        return(ret);
 }
 
-int _wapi_getsockopt(guint32 handle, int level, int optname, void *optval,
+int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval,
                     socklen_t *optlen)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
-       
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       struct timeval tv;
+       void *tmp_val;
+
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
-       
-       ret=getsockopt(socket_private_handle->fd, level, optname, optval,
-                      optlen);
-       if(ret==-1) {
+
+       tmp_val = optval;
+       if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
+               tmp_val = &tv;
+               *optlen = sizeof (tv);
+       }
+
+       ret = getsockopt (fd, level, optname, tmp_val, optlen);
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": getsockopt error: %s",
-                         strerror(errno));
+               g_message ("%s: getsockopt error: %s", __func__,
+                          strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
        }
+
+       if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
+               *((int *) optval)  = tv.tv_sec * 1000 + tv.tv_usec;
+               *optlen = sizeof (int);
+       }
+
+       if (optname == SO_ERROR) {
+               if (*((int *)optval) != 0) {
+                       *((int *) optval) = errno_to_WSA (*((int *)optval),
+                                                         __func__);
+               }
+       }
        
        return(ret);
 }
 
-int _wapi_listen(guint32 handle, int backlog)
+int _wapi_listen(guint32 fd, int backlog)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
        
-       ret=listen(socket_private_handle->fd, backlog);
-       if(ret==-1) {
+       ret = listen (fd, backlog);
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": listen error: %s",
-                         strerror(errno));
+               g_message ("%s: listen error: %s", __func__, strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
 
                return(SOCKET_ERROR);
@@ -512,53 +473,39 @@ int _wapi_listen(guint32 handle, int backlog)
        return(0);
 }
 
-int _wapi_recv(guint32 handle, void *buf, size_t len, int recv_flags)
+int _wapi_recv(guint32 fd, void *buf, size_t len, int recv_flags)
 {
-       return(_wapi_recvfrom(handle, buf, len, recv_flags, NULL, 0));
+       return(_wapi_recvfrom (fd, buf, len, recv_flags, NULL, 0));
 }
 
-int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags,
+int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags,
                   struct sockaddr *from, socklen_t *fromlen)
 {
-#ifndef HAVE_MSG_NOSIGNAL
-       void (*old_sigpipe)(int);       // old SIGPIPE handler
-#endif
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
        
-#ifdef HAVE_MSG_NOSIGNAL
-       ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags | MSG_NOSIGNAL, from,
-                    fromlen);
-#else
-       old_sigpipe = signal(SIGPIPE, SIG_IGN);
-       ret=recvfrom(socket_private_handle->fd, buf, len, recv_flags, from,
-                    fromlen);
-       signal(SIGPIPE, old_sigpipe);
-#endif
+       do {
+               ret = recvfrom (fd, buf, len, recv_flags, from, fromlen);
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending ());
 
-       if(ret==-1) {
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": recv error: %s",
-                         strerror(errno));
+               g_message ("%s: recv error: %s", __func__, strerror(errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -566,44 +513,33 @@ int _wapi_recvfrom(guint32 handle, void *buf, size_t len, int recv_flags,
        return(ret);
 }
 
-int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags)
+int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags)
 {
-#ifndef HAVE_MSG_NOSIGNAL
-       void (*old_sigpipe)(int);       // old SIGPIPE handler
-#endif
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
 
-#ifdef HAVE_MSG_NOSIGNAL
-       ret=send(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL);
-#else
-       old_sigpipe = signal(SIGPIPE, SIG_IGN);
-       ret=send(socket_private_handle->fd, msg, len, send_flags);
-       signal(SIGPIPE, old_sigpipe);
-#endif
-       if(ret==-1) {
+       do {
+               ret = send (fd, msg, len, send_flags);
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending ());
+
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
-                         strerror(errno));
+               g_message ("%s: send error: %s", __func__, strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -611,45 +547,34 @@ int _wapi_send(guint32 handle, const void *msg, size_t len, int send_flags)
        return(ret);
 }
 
-int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags,
+int _wapi_sendto(guint32 fd, const void *msg, size_t len, int send_flags,
                 const struct sockaddr *to, socklen_t tolen)
 {
-#ifndef HAVE_MSG_NOSIGNAL
-       void (*old_sigpipe)(int);       // old SIGPIPE handler
-#endif
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
        
-#ifdef HAVE_MSG_NOSIGNAL
-       ret=sendto(socket_private_handle->fd, msg, len, send_flags | MSG_NOSIGNAL, to, tolen);
-#else
-       old_sigpipe = signal(SIGPIPE, SIG_IGN);
-       ret=sendto(socket_private_handle->fd, msg, len, send_flags, to, tolen);
-       signal(SIGPIPE, old_sigpipe);
-#endif
-       if(ret==-1) {
+       do {
+               ret = sendto (fd, msg, len, send_flags, to, tolen);
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending ());
+
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": send error: %s",
-                         strerror(errno));
+               g_message ("%s: send error: %s", __func__, strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -657,37 +582,42 @@ int _wapi_sendto(guint32 handle, const void *msg, size_t len, int send_flags,
        return(ret);
 }
 
-int _wapi_setsockopt(guint32 handle, int level, int optname,
+int _wapi_setsockopt(guint32 fd, int level, int optname,
                     const void *optval, socklen_t optlen)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
+       const void *tmp_val;
+       struct timeval tv;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
-       
-       ret=setsockopt(socket_private_handle->fd, level, optname, optval,
-                      optlen);
-       if(ret==-1) {
+
+       tmp_val = optval;
+       if (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO) {
+               int ms = *((int *) optval);
+               tv.tv_sec = ms / 1000;
+               tv.tv_usec = ms % 1000;
+               tmp_val = &tv;
+               optlen = sizeof (tv);
+       }
+               
+       ret = setsockopt (fd, level, optname, tmp_val, optlen);
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": setsockopt error: %s",
-                         strerror(errno));
+               g_message ("%s: setsockopt error: %s", __func__,
+                          strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -696,35 +626,30 @@ int _wapi_setsockopt(guint32 handle, int level, int optname,
        return(ret);
 }
 
-int _wapi_shutdown(guint32 handle, int how)
+int _wapi_shutdown(guint32 fd, int how)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
        
-       ret=shutdown(socket_private_handle->fd, how);
-       if(ret==-1) {
+       ret = shutdown (fd, how);
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": shutdown error: %s",
-                         strerror(errno));
+               g_message ("%s: shutdown error: %s", __func__,
+                          strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -733,17 +658,15 @@ int _wapi_shutdown(guint32 handle, int how)
        return(ret);
 }
 
-guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 unused2, guint32 unused3)
+guint32 _wapi_socket(int domain, int type, int protocol, void *unused,
+                    guint32 unused2, guint32 unused3)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
        gpointer handle;
-       gboolean ok;
        int fd;
-       int thr_ret;
-       guint32 ret = INVALID_SOCKET;
        
-       fd=socket(domain, type, protocol);
-       if (fd==-1 && domain == AF_INET && type == SOCK_RAW && protocol == 0) {
+       fd = socket (domain, type, protocol);
+       if (fd == -1 && domain == AF_INET && type == SOCK_RAW &&
+           protocol == 0) {
                /* Retry with protocol == 4 (see bug #54565) */
                fd = socket (AF_INET, SOCK_RAW, 4);
        }
@@ -751,87 +674,76 @@ guint32 _wapi_socket(int domain, int type, int protocol, void *unused, guint32 u
        if (fd == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": socket error: %s", strerror(errno));
+               g_message ("%s: socket error: %s", __func__, strerror (errno));
 #endif
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
 
                return(INVALID_SOCKET);
        }
+
+       if (fd >= _wapi_fd_reserve) {
+#ifdef DEBUG
+               g_message ("%s: File descriptor is too big (%d >= %d)",
+                          __func__, fd, _wapi_fd_offset_table_size);
+#endif
+
+               WSASetLastError (WSASYSCALLFAILURE);
+               close (fd);
+               
+               return(INVALID_SOCKET);
+       }
+       
        
        mono_once (&socket_ops_once, socket_ops_init);
        
-       handle=_wapi_handle_new (WAPI_HANDLE_SOCKET);
-       if(handle==_WAPI_HANDLE_INVALID) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error creating socket handle");
+       handle = _wapi_handle_new_fd (WAPI_HANDLE_SOCKET, fd, NULL);
+       if (handle == _WAPI_HANDLE_INVALID) {
+               g_warning ("%s: error creating socket handle", __func__);
                return(INVALID_SOCKET);
        }
 
-       pthread_cleanup_push ((void(*)(void *))_wapi_handle_unlock_handle,
-                             handle);
-       thr_ret = _wapi_handle_lock_handle (handle);
-       g_assert (thr_ret == 0);
-       
-       ok=_wapi_lookup_handle (handle, WAPI_HANDLE_SOCKET, NULL,
-                               (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle %p", handle);
-               goto cleanup;
-       }
-       ret = GPOINTER_TO_UINT (handle);
-       
-       socket_private_handle->fd=fd;
-       
 #ifdef DEBUG
-       g_message(G_GNUC_PRETTY_FUNCTION
-                 ": returning socket handle %p with fd %d", handle,
-                 socket_private_handle->fd);
+       g_message ("%s: returning socket handle %p", __func__, handle);
 #endif
 
-cleanup:
-       thr_ret = _wapi_handle_unlock_handle (handle);
-       g_assert (thr_ret == 0);
-       pthread_cleanup_pop (0);
-       
-       return(ret);
+       return(fd);
 }
 
 struct hostent *_wapi_gethostbyname(const char *hostname)
 {
        struct hostent *he;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(NULL);
        }
 
-       he=gethostbyname(hostname);
-       if(he==NULL) {
+       he = gethostbyname (hostname);
+       if (he == NULL) {
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": gethostbyname error: %s",
-                         strerror(h_errno));
+               g_message ("%s: gethostbyname error: %s", __func__,
+                          strerror (h_errno));
 #endif
 
                switch(h_errno) {
                case HOST_NOT_FOUND:
-                       WSASetLastError(WSAHOST_NOT_FOUND);
+                       WSASetLastError (WSAHOST_NOT_FOUND);
                        break;
 #if NO_ADDRESS != NO_DATA
                case NO_ADDRESS:
 #endif
                case NO_DATA:
-                       WSASetLastError(WSANO_DATA);
+                       WSASetLastError (WSANO_DATA);
                        break;
                case NO_RECOVERY:
-                       WSASetLastError(WSANO_RECOVERY);
+                       WSASetLastError (WSANO_RECOVERY);
                        break;
                case TRY_AGAIN:
-                       WSASetLastError(WSATRY_AGAIN);
+                       WSASetLastError (WSATRY_AGAIN);
                        break;
                default:
-                       g_warning (G_GNUC_PRETTY_FUNCTION ": Need to translate %d into winsock error", h_errno);
+                       g_warning ("%s: Need to translate %d into winsock error", __func__, h_errno);
                        break;
                }
        }
@@ -840,120 +752,114 @@ struct hostent *_wapi_gethostbyname(const char *hostname)
 }
 
 int
-WSAIoctl (guint32 handle, gint32 command,
-               gchar *input, gint i_len,
-               gchar *output, gint o_len, glong *written,
-               void *unused1, void *unused2)
+WSAIoctl (guint32 fd, gint32 command,
+         gchar *input, gint i_len,
+         gchar *output, gint o_len, glong *written,
+         void *unused1, void *unused2)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        gchar *buffer = NULL;
 
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
 
-       ok = _wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                                       NULL, (gpointer *)&socket_private_handle);
-
-       if (ok == FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
                WSASetLastError (WSAENOTSOCK);
                return SOCKET_ERROR;
        }
 
-       if (i_len > 0)
+       if (i_len > 0) {
                buffer = g_memdup (input, i_len);
+       }
 
-       ret = ioctl (socket_private_handle->fd, command, buffer);
+       ret = ioctl (fd, command, buffer);
        if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": WSAIoctl error: %s",
-                         strerror(errno));
+               g_message("%s: WSAIoctl error: %s", __func__,
+                         strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                g_free (buffer);
                
-               return SOCKET_ERROR;
+               return(SOCKET_ERROR);
        }
 
        if (buffer == NULL) {
                *written = 0;
        } else {
                /* We just copy the buffer to the output. Some ioctls
-                * don't even output any data, but, well... */
+                * don't even output any data, but, well...
+                *
+                * NB windows returns WSAEFAULT if o_len is too small
+                */
                i_len = (i_len > o_len) ? o_len : i_len;
-               memcpy (output, buffer, i_len);
+
+               if (i_len > 0 && output != NULL) {
+                       memcpy (output, buffer, i_len);
+               }
+               
                g_free (buffer);
                *written = i_len;
        }
 
-       return 0;
+       return(0);
 }
 
-int ioctlsocket(guint32 handle, gint32 command, gpointer arg)
+int ioctlsocket(guint32 fd, gint32 command, gpointer arg)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
-               return(SOCKET_ERROR);
-       }
-
-       if(command!=FIONBIO &&
-          command!=FIONREAD &&
-          command!=SIOCATMARK) {
-               /* Not listed in the MSDN specs, but ioctl(2) returns
-                * this if command is invalid
-                */
-               WSASetLastError(WSAEINVAL);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(SOCKET_ERROR);
        }
 
+       switch(command){
+               case FIONBIO:
 #ifdef O_NONBLOCK
-       /* This works better than ioctl(...FIONBIO...) on Linux (it causes
-        * connect to return EINPROGRESS, but the ioctl doesn't seem to)
-        */
-       if(command==FIONBIO) {
-               ret=fcntl(socket_private_handle->fd, F_GETFL, 0);
-               if(ret!=-1) {
-                       if(*(gboolean *)arg) {
-                               ret &= ~O_NONBLOCK;
-                       } else {
-                               ret |= O_NONBLOCK;
+                       /* This works better than ioctl(...FIONBIO...) 
+                        * on Linux (it causes connect to return
+                        * EINPROGRESS, but the ioctl doesn't seem to)
+                        */
+                       ret = fcntl(fd, F_GETFL, 0);
+                       if (ret != -1) {
+                               if (*(gboolean *)arg) {
+                                       ret |= O_NONBLOCK;
+                               } else {
+                                       ret &= ~O_NONBLOCK;
+                               }
+                               ret = fcntl(fd, F_SETFL, ret);
                        }
-                       ret=fcntl(socket_private_handle->fd, F_SETFL, ret);
-               }
-       } else
+                       break;
 #endif /* O_NONBLOCK */
-       {
-               ret=ioctl(socket_private_handle->fd, command, arg);
+               case FIONREAD:
+               case SIOCATMARK:
+                       ret = ioctl (fd, command, arg);
+                       break;
+               default:
+                       WSASetLastError (WSAEINVAL);
+                       return(SOCKET_ERROR);
        }
-       if(ret==-1) {
+
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": ioctl error: %s",
-                         strerror(errno));
+               g_message ("%s: ioctl error: %s", __func__, strerror (errno));
 #endif
 
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -967,19 +873,23 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
 {
        int ret;
        
-       if(startup_count==0) {
-               WSASetLastError(WSANOTINITIALISED);
+       if (startup_count == 0) {
+               WSASetLastError (WSANOTINITIALISED);
                return(SOCKET_ERROR);
        }
 
-       ret=select(getdtablesize(), readfds, writefds, exceptfds, timeout);
-       if(ret==-1) {
+       do {
+               ret = select(getdtablesize (), readfds, writefds, exceptfds,
+                            timeout);
+       } while (ret == -1 && errno == EINTR &&
+                !_wapi_thread_cur_apc_pending ());
+
+       if (ret == -1) {
                gint errnum = errno;
 #ifdef DEBUG
-               g_message(G_GNUC_PRETTY_FUNCTION ": select error: %s",
-                         strerror(errno));
+               g_message ("%s: select error: %s", __func__, strerror (errno));
 #endif
-               errnum = errno_to_WSA (errnum, G_GNUC_PRETTY_FUNCTION);
+               errnum = errno_to_WSA (errnum, __func__);
                WSASetLastError (errnum);
                
                return(SOCKET_ERROR);
@@ -988,166 +898,39 @@ int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds,
        return(ret);
 }
 
-void _wapi_FD_CLR(guint32 handle, fd_set *set)
+void _wapi_FD_CLR(guint32 fd, fd_set *set)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return;
        }
 
-       FD_CLR(socket_private_handle->fd, set);
+       FD_CLR (fd, set);
 }
 
-int _wapi_FD_ISSET(guint32 handle, fd_set *set)
+int _wapi_FD_ISSET(guint32 fd, fd_set *set)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
+       gpointer handle = GUINT_TO_POINTER (fd);
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
+               WSASetLastError (WSAENOTSOCK);
                return(0);
        }
 
-       return(FD_ISSET(socket_private_handle->fd, set));
+       return(FD_ISSET (fd, set));
 }
 
-void _wapi_FD_SET(guint32 handle, fd_set *set)
+void _wapi_FD_SET(guint32 fd, fd_set *set)
 {
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
-       
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if(ok==FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", handle);
-               WSASetLastError(WSAENOTSOCK);
-               return;
-       }
-
-       FD_SET(socket_private_handle->fd, set);
-}
-
-#ifndef PLATFORM_WIN32
-#include <aio.h>
-
-typedef struct {
-       struct aiocb *aio;
-       gpointer ares;
-       SocketAsyncCB callback;
-} notifier_data_t;
-
-static void
-async_notifier (union sigval sig)
-{
-       notifier_data_t *ndata = sig.sival_ptr;
-       guint32 error;
-       guint32 numbytes;
-
-       error = aio_return (ndata->aio);
-       if (error < 0) {
-               error = _wapi_get_win32_error (error);
-               numbytes = 0;
-       } else {
-               numbytes = error;
-               error = 0;
-       }
-
-       ndata->callback (error, numbytes, ndata->ares);
-       g_free (ndata->aio);
-       g_free (ndata);
-}
-
-static gboolean
-do_aio_call (gboolean is_read, gpointer handle, gpointer buffer,
-               guint32 numbytes, guint32 *out_bytes,
-               gpointer ares,
-               SocketAsyncCB callback)
-{
-       struct _WapiHandlePrivate_socket *socket_private_handle;
-       gboolean ok;
-       int fd;
-       struct aiocb *aio;
-       int result;
-       notifier_data_t *ndata;
+       gpointer handle = GUINT_TO_POINTER (fd);
        
-       ok=_wapi_lookup_handle (GUINT_TO_POINTER (handle), WAPI_HANDLE_SOCKET,
-                               NULL, (gpointer *)&socket_private_handle);
-       if (ok == FALSE) {
-               g_warning (G_GNUC_PRETTY_FUNCTION
-                          ": error looking up socket handle 0x%x", (guint) handle);
+       if (_wapi_handle_type (handle) != WAPI_HANDLE_SOCKET) {
                WSASetLastError (WSAENOTSOCK);
-               return FALSE;
-       }
-
-       fd = socket_private_handle->fd;
-
-       ndata = g_new0 (notifier_data_t, 1);
-       aio = g_new0 (struct aiocb, 1);
-       ndata->ares = ares;
-       ndata->aio = aio;
-       ndata->callback = callback;
-
-       aio->aio_fildes = fd;
-       aio->aio_lio_opcode = (is_read) ? LIO_READ : LIO_WRITE;
-       aio->aio_nbytes = numbytes;
-       aio->aio_offset = 0;
-       aio->aio_buf = buffer;
-       aio->aio_sigevent.sigev_notify = SIGEV_THREAD;
-       aio->aio_sigevent.sigev_notify_function = async_notifier;
-       aio->aio_sigevent.sigev_value.sival_ptr = ndata;
-
-       if (is_read) {
-               result = aio_read (aio);
-       } else {
-               result = aio_write (aio);
-       }
-
-       if (result == -1) {
-               WSASetLastError (errno_to_WSA (errno, "do_aio_call"));
-               return FALSE;
-       }
-
-       result = aio_error (aio);
-       if (result == 0) {
-               numbytes = aio_return (aio);
-       } else {
-               WSASetLastError (errno_to_WSA (result, "do_aio_call"));
-               return FALSE;
+               return;
        }
 
-       if (out_bytes)
-               *out_bytes = numbytes;
-
-       return TRUE;
-}
-
-gboolean _wapi_socket_async_read (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *bytesread, gpointer ares,
-                                 SocketAsyncCB callback)
-{
-       return do_aio_call (TRUE, handle, buffer, numbytes, bytesread, ares, callback);
+       FD_SET (fd, set);
 }
 
-gboolean _wapi_socket_async_write (gpointer handle, gpointer buffer,
-                                 guint32 numbytes,
-                                 guint32 *byteswritten, gpointer ares,
-                                 SocketAsyncCB callback)
-{
-       return do_aio_call (FALSE, handle, buffer, numbytes, byteswritten, ares, callback);
-}
-
-#endif /* !PLATFORM_WIN32 */
-