int mono_w32socket_sendto (SOCKET sock, const char *buf, int len, int flags, const struct sockaddr *to, int tolen, gboolean blocking) { gpointer handle; int ret; MonoThreadInfo *info; handle = GUINT_TO_POINTER (sock); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { mono_w32socket_set_last_error (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); do { ret = sendto (sock, buf, len, flags, to, tolen); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } return ret; }
static void socket_close (gpointer handle, gpointer data) { int ret; MonoW32HandleSocket *socket_handle = (MonoW32HandleSocket *)data; MonoThreadInfo *info = mono_thread_info_current (); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: closing socket handle %p", __func__, handle); /* Shutdown the socket for reading, to interrupt any potential * receives that may be blocking for data. See bug 75705. */ shutdown (GPOINTER_TO_UINT (handle), SHUT_RD); do { ret = close (GPOINTER_TO_UINT(handle)); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: close error: %s", __func__, g_strerror (errno)); if (!in_cleanup) mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); } if (!in_cleanup) socket_handle->saved_error = 0; }
static int _wapi_sendmsg(guint32 fd, const struct msghdr *msg, int send_flags) { gpointer handle = GUINT_TO_POINTER (fd); int ret; MonoThreadInfo *info = mono_thread_info_current (); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } do { ret = sendmsg (fd, msg, send_flags); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, strerror (errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(SOCKET_ERROR); } return(ret); }
int _wapi_recvfrom(guint32 fd, void *buf, size_t len, int recv_flags, struct sockaddr *from, socklen_t *fromlen) { gpointer handle = GUINT_TO_POINTER (fd); struct _WapiHandle_socket *socket_handle; gboolean ok; int ret; MonoThreadInfo *info = mono_thread_info_current (); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } do { ret = recvfrom (fd, buf, len, recv_flags, from, fromlen); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == 0 && len > 0) { /* According to the Linux man page, recvfrom only * returns 0 when the socket has been shut down * cleanly. Turn this into an EINTR to simulate win32 * behaviour of returning EINTR when a socket is * closed while the recvfrom is blocking (we use a * shutdown() in socket_close() to trigger this.) See * bug 75705. */ /* Distinguish between the socket being shut down at * the local or remote ends, and reads that request 0 * bytes to be read */ /* If this returns FALSE, it means the socket has been * closed locally. If it returns TRUE, but * still_readable != 1 then shutdown * (SHUT_RD|SHUT_RDWR) has been called locally. */ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE || socket_handle->still_readable != 1) { ret = -1; errno = EINTR; } } if (ret == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, strerror(errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(SOCKET_ERROR); } return(ret); }
int mono_w32socket_recvfrom (SOCKET sock, char *buf, int len, int flags, struct sockaddr *from, socklen_t *fromlen, gboolean blocking) { gpointer handle; MonoW32HandleSocket *socket_handle; int ret; MonoThreadInfo *info; handle = GUINT_TO_POINTER (sock); if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { mono_w32socket_set_last_error (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); do { ret = recvfrom (sock, buf, len, flags, from, fromlen); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == 0 && len > 0) { /* According to the Linux man page, recvfrom only * returns 0 when the socket has been shut down * cleanly. Turn this into an EINTR to simulate win32 * behaviour of returning EINTR when a socket is * closed while the recvfrom is blocking (we use a * shutdown() in socket_close() to trigger this.) See * bug 75705. */ /* Distinguish between the socket being shut down at * the local or remote ends, and reads that request 0 * bytes to be read */ /* If this returns FALSE, it means the socket has been * closed locally. If it returns TRUE, but * still_readable != 1 then shutdown * (SHUT_RD|SHUT_RDWR) has been called locally. */ if (socket_handle->still_readable != 1) { ret = -1; errno = EINTR; } } if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recv error: %s", __func__, g_strerror(errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } return ret; }
int mono_w32socket_recvbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *received, guint32 *flags, gpointer overlapped, gpointer complete, gboolean blocking) { MonoW32HandleSocket *socket_handle; MonoThreadInfo *info; gpointer handle; gint ret; struct msghdr hdr; g_assert (overlapped == NULL); g_assert (complete == NULL); handle = GUINT_TO_POINTER (sock); if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { mono_w32socket_set_last_error (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); wsabuf_to_msghdr (buffers, count, &hdr); do { ret = recvmsg (sock, &hdr, *flags); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); msghdr_iov_free (&hdr); if (ret == 0) { /* see mono_w32socket_recvfrom */ if (socket_handle->still_readable != 1) { ret = -1; errno = EINTR; } } if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, g_strerror(errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } *received = ret; *flags = hdr.msg_flags; return 0; }
static int _wapi_recvmsg(guint32 fd, struct msghdr *msg, int recv_flags) { gpointer handle = GUINT_TO_POINTER (fd); struct _WapiHandle_socket *socket_handle; gboolean ok; int ret; MonoThreadInfo *info = mono_thread_info_current (); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } do { ret = recvmsg (fd, msg, recv_flags); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == 0) { /* see _wapi_recvfrom */ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE || socket_handle->still_readable != 1) { ret = -1; errno = EINTR; } } if (ret == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: recvmsg error: %s", __func__, strerror(errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(SOCKET_ERROR); } return(ret); }
int mono_w32socket_sendbuffers (SOCKET sock, WSABUF *buffers, guint32 count, guint32 *sent, guint32 flags, gpointer overlapped, gpointer complete, gboolean blocking) { struct msghdr hdr; MonoThreadInfo *info; gpointer handle; gint ret; g_assert (overlapped == NULL); g_assert (complete == NULL); handle = GUINT_TO_POINTER (sock); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { mono_w32socket_set_last_error (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); wsabuf_to_msghdr (buffers, count, &hdr); do { ret = sendmsg (sock, &hdr, flags); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); msghdr_iov_free (&hdr); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: sendmsg error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } *sent = ret; return 0; }
int mono_w32socket_send (SOCKET sock, char *buf, int len, int flags, gboolean blocking) { gpointer handle; int ret; MonoThreadInfo *info; handle = GUINT_TO_POINTER (sock); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { mono_w32socket_set_last_error (WSAENOTSOCK); return SOCKET_ERROR; } info = mono_thread_info_current (); do { ret = send (sock, buf, len, flags); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, g_strerror (errno)); #ifdef O_NONBLOCK /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on * a blocking socket. See bug #599488 */ if (errnum == EAGAIN) { ret = fcntl (sock, F_GETFL, 0); if (ret != -1 && (ret & O_NONBLOCK) == 0) errnum = ETIMEDOUT; } #endif /* O_NONBLOCK */ mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } return ret; }
int _wapi_send(guint32 fd, const void *msg, size_t len, int send_flags) { gpointer handle = GUINT_TO_POINTER (fd); int ret; MonoThreadInfo *info = mono_thread_info_current (); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } do { ret = send (fd, msg, len, send_flags); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: send error: %s", __func__, strerror (errno)); #ifdef O_NONBLOCK /* At least linux returns EAGAIN/EWOULDBLOCK when the timeout has been set on * a blocking socket. See bug #599488 */ if (errnum == EAGAIN) { ret = fcntl (fd, F_GETFL, 0); if (ret != -1 && (ret & O_NONBLOCK) == 0) errnum = ETIMEDOUT; } #endif /* O_NONBLOCK */ errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(SOCKET_ERROR); } return(ret); }
int _wapi_select(int nfds G_GNUC_UNUSED, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { int ret, maxfd; MonoThreadInfo *info = mono_thread_info_current (); for (maxfd = FD_SETSIZE-1; maxfd >= 0; maxfd--) { if ((readfds && FD_ISSET (maxfd, readfds)) || (writefds && FD_ISSET (maxfd, writefds)) || (exceptfds && FD_ISSET (maxfd, exceptfds))) { break; } } if (maxfd == -1) { WSASetLastError (WSAEINVAL); return(SOCKET_ERROR); } do { ret = select(maxfd + 1, readfds, writefds, exceptfds, timeout); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: select error: %s", __func__, strerror (errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(SOCKET_ERROR); } return(ret); }
BOOL mono_w32socket_transmit_file (SOCKET sock, gpointer file_handle, TRANSMIT_FILE_BUFFERS *buffers, guint32 flags, gboolean blocking) { MonoThreadInfo *info; gpointer handle; gint file; gssize ret; #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) struct stat statbuf; #else gchar *buffer; #endif handle = GUINT_TO_POINTER (sock); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { mono_w32socket_set_last_error (WSAENOTSOCK); return FALSE; } /* Write the header */ if (buffers != NULL && buffers->Head != NULL && buffers->HeadLength > 0) { ret = mono_w32socket_send (sock, buffers->Head, buffers->HeadLength, 0, FALSE); if (ret == SOCKET_ERROR) return FALSE; } info = mono_thread_info_current (); file = GPOINTER_TO_INT (file_handle); #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) ret = fstat (file, &statbuf); if (ret == -1) { gint errnum = errno; mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } do { #ifdef __linux__ ret = sendfile (sock, file, NULL, statbuf.st_size); #elif defined(DARWIN) /* TODO: header/tail could be sent in the 5th argument */ /* TODO: Might not send the entire file for non-blocking sockets */ ret = sendfile (file, sock, 0, &statbuf.st_size, NULL, 0); #endif } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); #else buffer = g_malloc (SF_BUFFER_SIZE); do { do { ret = read (file, buffer, SF_BUFFER_SIZE); } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (ret == -1 || ret == 0) break; do { ret = send (sock, buffer, ret, 0); /* short sends? enclose this in a loop? */ } while (ret == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); } while (ret != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); g_free (buffer); #endif if (ret == -1) { gint errnum = errno; mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return FALSE; } /* Write the tail */ if (buffers != NULL && buffers->Tail != NULL && buffers->TailLength > 0) { ret = mono_w32socket_send (sock, buffers->Tail, buffers->TailLength, 0, FALSE); if (ret == SOCKET_ERROR) return FALSE; } if ((flags & TF_DISCONNECT) == TF_DISCONNECT) mono_w32handle_close (handle); return TRUE; }
guint32 _wapi_accept(guint32 fd, struct sockaddr *addr, socklen_t *addrlen) { gpointer handle = GUINT_TO_POINTER (fd); gpointer new_handle; struct _WapiHandle_socket *socket_handle; struct _WapiHandle_socket new_socket_handle = {0}; gboolean ok; int new_fd; MonoThreadInfo *info = mono_thread_info_current (); if (addr != NULL && *addrlen < sizeof(struct sockaddr)) { WSASetLastError (WSAEFAULT); return(INVALID_SOCKET); } if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(INVALID_SOCKET); } ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", __func__, handle); WSASetLastError (WSAENOTSOCK); return(INVALID_SOCKET); } do { new_fd = accept (fd, addr, addrlen); } while (new_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (new_fd == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, strerror(errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(INVALID_SOCKET); } if (new_fd >= mono_w32handle_fd_reserve) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); WSASetLastError (WSASYSCALLFAILURE); close (new_fd); return(INVALID_SOCKET); } new_socket_handle.domain = socket_handle->domain; new_socket_handle.type = socket_handle->type; new_socket_handle.protocol = socket_handle->protocol; new_socket_handle.still_readable = 1; new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd, &new_socket_handle); if(new_handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating socket handle", __func__); WSASetLastError (ERROR_GEN_FAILURE); return(INVALID_SOCKET); } MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with", __func__, new_handle); return(new_fd); }
SOCKET mono_w32socket_accept (SOCKET sock, struct sockaddr *addr, socklen_t *addrlen, gboolean blocking) { gpointer handle; gpointer new_handle; MonoW32HandleSocket *socket_handle; MonoW32HandleSocket new_socket_handle; SOCKET new_fd; MonoThreadInfo *info; if (addr != NULL && *addrlen < sizeof(struct sockaddr)) { mono_w32socket_set_last_error (WSAEFAULT); return INVALID_SOCKET; } handle = GUINT_TO_POINTER (sock); if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { mono_w32socket_set_last_error (WSAENOTSOCK); return INVALID_SOCKET; } info = mono_thread_info_current (); do { new_fd = accept (sock, addr, addrlen); } while (new_fd == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (new_fd == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: accept error: %s", __func__, g_strerror(errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return INVALID_SOCKET; } if (new_fd >= mono_w32handle_fd_reserve) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: File descriptor is too big", __func__); mono_w32socket_set_last_error (WSASYSCALLFAILURE); close (new_fd); return INVALID_SOCKET; } new_socket_handle.domain = socket_handle->domain; new_socket_handle.type = socket_handle->type; new_socket_handle.protocol = socket_handle->protocol; new_socket_handle.still_readable = 1; new_handle = mono_w32handle_new_fd (MONO_W32HANDLE_SOCKET, new_fd, &new_socket_handle); if(new_handle == INVALID_HANDLE_VALUE) { g_warning ("%s: error creating socket handle", __func__); mono_w32socket_set_last_error (ERROR_GEN_FAILURE); return INVALID_SOCKET; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: returning newly accepted socket handle %p with", __func__, new_handle); return new_fd; }
static gint wapi_sendfile (guint32 socket, gpointer fd, guint32 bytes_to_write, guint32 bytes_per_send, guint32 flags) { MonoThreadInfo *info = mono_thread_info_current (); #if defined(HAVE_SENDFILE) && (defined(__linux__) || defined(DARWIN)) gint file = GPOINTER_TO_INT (fd); gint n; gint errnum; gssize res; struct stat statbuf; n = fstat (file, &statbuf); if (n == -1) { errnum = errno; errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return SOCKET_ERROR; } do { #ifdef __linux__ res = sendfile (socket, file, NULL, statbuf.st_size); #elif defined(DARWIN) /* TODO: header/tail could be sent in the 5th argument */ /* TODO: Might not send the entire file for non-blocking sockets */ res = sendfile (file, socket, 0, &statbuf.st_size, NULL, 0); #endif } while (res != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (res == -1) { errnum = errno; errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return SOCKET_ERROR; } #else /* Default implementation */ gint file = GPOINTER_TO_INT (fd); gchar *buffer; gint n; buffer = g_malloc (SF_BUFFER_SIZE); do { do { n = read (file, buffer, SF_BUFFER_SIZE); } while (n == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (n == -1) break; if (n == 0) { g_free (buffer); return 0; /* We're done reading */ } do { n = send (socket, buffer, n, 0); /* short sends? enclose this in a loop? */ } while (n == -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); } while (n != -1 && errno == EINTR && !mono_thread_info_is_interrupt_state (info)); if (n == -1) { gint errnum = errno; errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); g_free (buffer); return SOCKET_ERROR; } g_free (buffer); #endif return 0; }
int _wapi_connect(guint32 fd, const struct sockaddr *serv_addr, socklen_t addrlen) { gpointer handle = GUINT_TO_POINTER (fd); struct _WapiHandle_socket *socket_handle; gboolean ok; gint errnum; MonoThreadInfo *info = mono_thread_info_current (); if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } if (connect (fd, serv_addr, addrlen) == -1) { mono_pollfd fds; int so_error; socklen_t len; errnum = errno; if (errno != EINTR) { MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__, strerror (errnum)); errnum = errno_to_WSA (errnum, __func__); if (errnum == WSAEINPROGRESS) errnum = WSAEWOULDBLOCK; /* see bug #73053 */ WSASetLastError (errnum); /* * On solaris x86 getsockopt (SO_ERROR) is not set after * connect () fails so we need to save this error. * * But don't do this for EWOULDBLOCK (bug 317315) */ if (errnum != WSAEWOULDBLOCK) { ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { /* ECONNRESET means the socket was closed by another thread */ /* Async close on mac raises ECONNABORTED. */ if (errnum != WSAECONNRESET && errnum != WSAENETDOWN) g_warning ("%s: error looking up socket handle %p (error %d)", __func__, handle, errnum); } else { socket_handle->saved_error = errnum; } } return(SOCKET_ERROR); } fds.fd = fd; fds.events = MONO_POLLOUT; while (mono_poll (&fds, 1, -1) == -1 && !mono_thread_info_is_interrupt_state (info)) { if (errno != EINTR) { errnum = errno_to_WSA (errno, __func__); MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, strerror (errno)); WSASetLastError (errnum); return(SOCKET_ERROR); } } len = sizeof(so_error); if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) { errnum = errno_to_WSA (errno, __func__); MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, strerror (errno)); WSASetLastError (errnum); return(SOCKET_ERROR); } if (so_error != 0) { errnum = errno_to_WSA (so_error, __func__); /* Need to save this socket error */ ok = mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle); if (ok == FALSE) { g_warning ("%s: error looking up socket handle %p", __func__, handle); } else { socket_handle->saved_error = errnum; } MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s", __func__, strerror (so_error)); WSASetLastError (errnum); return(SOCKET_ERROR); } } return(0); }
gint mono_thread_info_sleep (guint32 ms, gboolean *alerted) { if (ms == 0) { MonoThreadInfo *info; mono_thread_info_yield (); info = mono_thread_info_current (); if (info && mono_thread_info_is_interrupt_state (info)) return WAIT_IO_COMPLETION; return 0; } if (alerted) return sleep_interruptable (ms, alerted); MONO_PREPARE_BLOCKING; if (ms == INFINITE) { do { #ifdef HOST_WIN32 Sleep (G_MAXUINT32); #else sleep (G_MAXUINT32); #endif } while (1); } else { int ret; #if defined (__linux__) && !defined(PLATFORM_ANDROID) struct timespec start, target; /* Use clock_nanosleep () to prevent time drifting problems when nanosleep () is interrupted by signals */ ret = clock_gettime (CLOCK_MONOTONIC, &start); g_assert (ret == 0); target = start; target.tv_sec += ms / 1000; target.tv_nsec += (ms % 1000) * 1000000; if (target.tv_nsec > 999999999) { target.tv_nsec -= 999999999; target.tv_sec ++; } do { ret = clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &target, NULL); } while (ret != 0); #elif HOST_WIN32 Sleep (ms); #else struct timespec req, rem; req.tv_sec = ms / 1000; req.tv_nsec = (ms % 1000) * 1000000; do { memset (&rem, 0, sizeof (rem)); ret = nanosleep (&req, &rem); } while (ret != 0); #endif /* __linux__ */ } MONO_FINISH_BLOCKING; return 0; }
int mono_w32socket_connect (SOCKET sock, const struct sockaddr *addr, int addrlen, gboolean blocking) { gpointer handle; MonoW32HandleSocket *socket_handle; handle = GUINT_TO_POINTER (sock); if (!mono_w32handle_lookup (handle, MONO_W32HANDLE_SOCKET, (gpointer *)&socket_handle)) { mono_w32socket_set_last_error (WSAENOTSOCK); return SOCKET_ERROR; } if (connect (sock, addr, addrlen) == -1) { MonoThreadInfo *info; mono_pollfd fds; gint errnum, so_error; socklen_t len; errnum = errno; if (errno != EINTR) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect error: %s", __func__, g_strerror (errnum)); errnum = mono_w32socket_convert_error (errnum); if (errnum == WSAEINPROGRESS) errnum = WSAEWOULDBLOCK; /* see bug #73053 */ mono_w32socket_set_last_error (errnum); /* * On solaris x86 getsockopt (SO_ERROR) is not set after * connect () fails so we need to save this error. * * But don't do this for EWOULDBLOCK (bug 317315) */ if (errnum != WSAEWOULDBLOCK) { /* ECONNRESET means the socket was closed by another thread */ /* Async close on mac raises ECONNABORTED. */ socket_handle->saved_error = errnum; } return SOCKET_ERROR; } info = mono_thread_info_current (); fds.fd = sock; fds.events = MONO_POLLOUT; while (mono_poll (&fds, 1, -1) == -1 && !mono_thread_info_is_interrupt_state (info)) { if (errno != EINTR) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect poll error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } } len = sizeof(so_error); if (getsockopt (sock, SOL_SOCKET, SO_ERROR, &so_error, &len) == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } if (so_error != 0) { gint errnum = mono_w32socket_convert_error (so_error); /* Need to save this socket error */ socket_handle->saved_error = errnum; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: connect getsockopt returned error: %s", __func__, g_strerror (so_error)); mono_w32socket_set_last_error (errnum); return SOCKET_ERROR; } } return 0; }