gint mono_w32socket_shutdown (SOCKET sock, gint how) { MonoW32HandleSocket *socket_handle; gpointer handle; gint ret; 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 (how == SHUT_RD || how == SHUT_RDWR) socket_handle->still_readable = 0; ret = shutdown (sock, how); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } return ret; }
static gboolean mutex_handle_own (gpointer handle, MonoW32HandleType type, gboolean *abandoned) { MonoW32HandleMutex *mutex_handle; *abandoned = FALSE; if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p, before: [tid: %p, recursion: %d], after: [tid: %p, recursion: %d], abandoned: %s", __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion, (gpointer) pthread_self (), mutex_handle->recursion + 1, mutex_handle->abandoned ? "true" : "false"); if (mutex_handle->recursion != 0) { g_assert (pthread_equal (pthread_self (), mutex_handle->tid)); mutex_handle->recursion++; } else { mutex_handle->tid = pthread_self (); mutex_handle->recursion = 1; thread_own_mutex (mono_thread_internal_current (), handle); } if (mutex_handle->abandoned) { mutex_handle->abandoned = FALSE; *abandoned = TRUE; } mono_w32handle_set_signal_state (handle, FALSE, FALSE); return TRUE; }
static gboolean event_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode) { MonoW32HandleEvent *event_handle; gboolean ok; *statuscode = WAIT_OBJECT_0; ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle); if (!ok) { g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p", __func__, mono_w32handle_ops_typename (type), handle); if (!event_handle->manual) { g_assert (event_handle->set_count > 0); event_handle->set_count --; if (event_handle->set_count == 0) mono_w32handle_set_signal_state (handle, FALSE, FALSE); } return TRUE; }
static gboolean event_handle_own (gpointer handle, MonoW32HandleType type) { struct _WapiHandle_event *event_handle; gboolean ok; ok = mono_w32handle_lookup (handle, type, (gpointer *)&event_handle); if (!ok) { g_warning ("%s: error looking up %s handle %p", __func__, event_handle_type_to_string (type), handle); return FALSE; } MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p", __func__, event_handle_type_to_string (type), handle); if (!event_handle->manual) { g_assert (event_handle->set_count > 0); event_handle->set_count --; if (event_handle->set_count == 0) mono_w32handle_set_signal_state (handle, FALSE, FALSE); } return TRUE; }
MonoBoolean ves_icall_System_Threading_Semaphore_ReleaseSemaphore_internal (gpointer handle, gint32 releaseCount, gint32 *prevcount) { MonoW32HandleType type; MonoW32HandleSemaphore *sem_handle; int thr_ret; MonoBoolean ret; if (!handle) { SetLastError (ERROR_INVALID_HANDLE); return FALSE; } switch (type = mono_w32handle_get_type (handle)) { case MONO_W32HANDLE_SEM: case MONO_W32HANDLE_NAMEDSEM: break; default: SetLastError (ERROR_INVALID_HANDLE); return FALSE; } if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) { g_warning ("%s: error looking up sem handle %p", __func__, handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p", __func__, mono_w32handle_ops_typename (type), handle); thr_ret = mono_w32handle_lock_handle (handle); g_assert (thr_ret == 0); /* Do this before checking for count overflow, because overflowing * max is a listed technique for finding the current value */ if (prevcount) *prevcount = sem_handle->val; /* No idea why max is signed, but thats the spec :-( */ if (sem_handle->val + releaseCount > (guint32)sem_handle->max) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d, max value would be exceeded", __func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max); ret = FALSE; } else { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p val %d count %d max %d", __func__, mono_w32handle_ops_typename (type), handle, sem_handle->val, releaseCount, sem_handle->max); sem_handle->val += releaseCount; mono_w32handle_set_signal_state (handle, TRUE, TRUE); ret = TRUE; } thr_ret = mono_w32handle_unlock_handle (handle); g_assert (thr_ret == 0); 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; }
static gboolean socket_disconnect (guint32 fd) { struct _WapiHandle_socket *socket_handle; gboolean ok; gpointer handle = GUINT_TO_POINTER (fd); int newsock, ret; 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(FALSE); } newsock = socket (socket_handle->domain, socket_handle->type, socket_handle->protocol); if (newsock == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, strerror (errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(FALSE); } /* According to Stevens "Advanced Programming in the UNIX * Environment: UNIX File I/O" dup2() is atomic so there * should not be a race condition between the old fd being * closed and the new socket fd being copied over */ do { ret = dup2 (newsock, fd); } while (ret == -1 && errno == EAGAIN); if (ret == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, strerror (errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(FALSE); } close (newsock); return(TRUE); }
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; }
gint mono_w32socket_disconnect (SOCKET sock, gboolean reuse) { MonoW32HandleSocket *socket_handle; gpointer handle; SOCKET newsock; gint ret; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: called on socket %d!", __func__, sock); /* We could check the socket type here and fail unless its * SOCK_STREAM, SOCK_SEQPACKET or SOCK_RDM (according to msdn) * if we really wanted to */ 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; } newsock = socket (socket_handle->domain, socket_handle->type, socket_handle->protocol); if (newsock == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: socket error: %s", __func__, g_strerror (errnum)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } /* According to Stevens "Advanced Programming in the UNIX * Environment: UNIX File I/O" dup2() is atomic so there * should not be a race condition between the old fd being * closed and the new socket fd being copied over */ do { ret = dup2 (newsock, sock); } while (ret == -1 && errno == EAGAIN); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: dup2 error: %s", __func__, g_strerror (errnum)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } close (newsock); return 0; }
gint mono_w32socket_getsockopt (SOCKET sock, gint level, gint optname, gpointer optval, socklen_t *optlen) { gpointer handle; gint ret; struct timeval tv; gpointer tmp_val; 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; } tmp_val = optval; if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { tmp_val = &tv; *optlen = sizeof (tv); } ret = getsockopt (sock, level, optname, tmp_val, optlen); if (ret == -1) { gint errnum = errno; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, g_strerror (errno)); mono_w32socket_set_last_error (mono_w32socket_convert_error (errnum)); return SOCKET_ERROR; } if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro *optlen = sizeof (int); } if (optname == SO_ERROR) { if (*((int *)optval) != 0) { *((int *) optval) = mono_w32socket_convert_error (*((int *)optval)); socket_handle->saved_error = *((int *)optval); } else { *((int *)optval) = socket_handle->saved_error; } } return 0; }
static void mutex_handle_prewait (gpointer handle, MonoW32HandleType type) { /* If the mutex is not currently owned, do nothing and let the * usual wait carry on. If it is owned, check that the owner * is still alive; if it isn't we override the previous owner * and assume that process exited abnormally and failed to * clean up. */ MonoW32HandleMutex *mutex_handle; if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: pre-waiting %s handle %p, owned? %s", __func__, mono_w32handle_get_typename (type), handle, mutex_handle->recursion != 0 ? "true" : "false"); }
int _wapi_shutdown(guint32 fd, int how) { struct _WapiHandle_socket *socket_handle; gboolean ok; gpointer handle = GUINT_TO_POINTER (fd); int ret; if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } if (how == SHUT_RD || how == SHUT_RDWR) { 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(SOCKET_ERROR); } socket_handle->still_readable = 0; } ret = shutdown (fd, how); if (ret == -1) { gint errnum = errno; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: shutdown error: %s", __func__, strerror (errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(SOCKET_ERROR); } return(ret); }
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); }
static gboolean sem_handle_own (gpointer handle, MonoW32HandleType type, guint32 *statuscode) { MonoW32HandleSemaphore *sem_handle; *statuscode = WAIT_OBJECT_0; if (!mono_w32handle_lookup (handle, type, (gpointer *)&sem_handle)) { g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_ops_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: owning %s handle %p", __func__, mono_w32handle_ops_typename (type), handle); sem_handle->val--; if (sem_handle->val == 0) mono_w32handle_set_signal_state (handle, FALSE, FALSE); return TRUE; }
static gboolean mutex_handle_is_owned (gpointer handle, MonoW32HandleType type) { MonoW32HandleMutex *mutex_handle; if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: testing ownership %s handle %p", __func__, mono_w32handle_get_typename (type), handle); if (mutex_handle->recursion > 0 && pthread_equal (mutex_handle->tid, pthread_self ())) { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p owned by %p", __func__, mono_w32handle_get_typename (type), handle, (gpointer) pthread_self ()); return TRUE; } else { mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: %s handle %p not owned by %p, tid: %p recursion: %d", __func__, mono_w32handle_get_typename (type), handle, (gpointer) pthread_self (), (gpointer) mutex_handle->tid, mutex_handle->recursion); return FALSE; } }
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); }
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; }
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; }
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); }
void mono_w32mutex_abandon (void) { MonoInternalThread *internal; g_assert (mono_thread_internal_current_is_attached ()); internal = mono_thread_internal_current (); g_assert (internal); if (!internal->owned_mutexes) return; while (internal->owned_mutexes->len) { MonoW32HandleType type; MonoW32HandleMutex *mutex_handle; MonoNativeThreadId tid; gpointer handle; handle = g_ptr_array_index (internal->owned_mutexes, 0); switch (type = mono_w32handle_get_type (handle)) { case MONO_W32HANDLE_MUTEX: case MONO_W32HANDLE_NAMEDMUTEX: break; default: g_assert_not_reached (); } if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { g_error ("%s: error looking up %s handle %p", __func__, mono_w32handle_get_typename (type), handle); } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoning %s handle %p", __func__, mono_w32handle_get_typename (type), handle); tid = MONO_UINT_TO_NATIVE_THREAD_ID (internal->tid); if (!pthread_equal (mutex_handle->tid, tid)) g_error ("%s: trying to release mutex %p acquired by thread %p from thread %p", __func__, handle, (gpointer) mutex_handle->tid, (gpointer) tid); mono_w32handle_lock_handle (handle); mutex_handle->recursion = 0; mutex_handle->tid = 0; mutex_handle->abandoned = TRUE; mono_w32handle_set_signal_state (handle, TRUE, FALSE); thread_disown_mutex (internal, handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: abandoned %s handle %p", __func__, mono_w32handle_get_typename (type), handle); mono_w32handle_unlock_handle (handle); } g_ptr_array_free (internal->owned_mutexes, TRUE); internal->owned_mutexes = NULL; }
MonoBoolean ves_icall_System_Threading_Mutex_ReleaseMutex_internal (gpointer handle) { MonoW32HandleType type; MonoW32HandleMutex *mutex_handle; pthread_t tid; gboolean ret; if (handle == NULL) { mono_w32error_set_last (ERROR_INVALID_HANDLE); return FALSE; } switch (type = mono_w32handle_get_type (handle)) { case MONO_W32HANDLE_MUTEX: case MONO_W32HANDLE_NAMEDMUTEX: break; default: mono_w32error_set_last (ERROR_INVALID_HANDLE); return FALSE; } if (!mono_w32handle_lookup (handle, type, (gpointer *)&mutex_handle)) { g_warning ("%s: error looking up %s handle %p", __func__, mono_w32handle_get_typename (type), handle); return FALSE; } mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: releasing %s handle %p, tid: %p recursion: %d", __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion); mono_w32handle_lock_handle (handle); tid = pthread_self (); if (mutex_handle->abandoned) { // The Win32 ReleaseMutex() function returns TRUE for abandoned mutexes ret = TRUE; } else if (!pthread_equal (mutex_handle->tid, tid)) { ret = FALSE; mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: we don't own %s handle %p (owned by %ld, me %ld)", __func__, mono_w32handle_get_typename (type), handle, (long)mutex_handle->tid, (long)tid); } else { ret = TRUE; /* OK, we own this mutex */ mutex_handle->recursion--; if (mutex_handle->recursion == 0) { thread_disown_mutex (mono_thread_internal_current (), handle); mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: unlocking %s handle %p, tid: %p recusion : %d", __func__, mono_w32handle_get_typename (type), handle, (gpointer) mutex_handle->tid, mutex_handle->recursion); mutex_handle->tid = 0; mono_w32handle_set_signal_state (handle, TRUE, FALSE); } } mono_w32handle_unlock_handle (handle); return ret; }
int _wapi_getsockopt(guint32 fd, int level, int optname, void *optval, socklen_t *optlen) { gpointer handle = GUINT_TO_POINTER (fd); int ret; struct timeval tv; void *tmp_val; struct _WapiHandle_socket *socket_handle; gboolean ok; if (mono_w32handle_get_type (handle) != MONO_W32HANDLE_SOCKET) { WSASetLastError (WSAENOTSOCK); return(SOCKET_ERROR); } tmp_val = optval; if (level == SOL_SOCKET && (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; MONO_TRACE (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: getsockopt error: %s", __func__, strerror (errno)); errnum = errno_to_WSA (errnum, __func__); WSASetLastError (errnum); return(SOCKET_ERROR); } if (level == SOL_SOCKET && (optname == SO_RCVTIMEO || optname == SO_SNDTIMEO)) { *((int *) optval) = tv.tv_sec * 1000 + (tv.tv_usec / 1000); // milli from micro *optlen = sizeof (int); } if (optname == SO_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); /* can't extract the last error */ *((int *) optval) = errno_to_WSA (*((int *)optval), __func__); } else { if (*((int *)optval) != 0) { *((int *) optval) = errno_to_WSA (*((int *)optval), __func__); socket_handle->saved_error = *((int *)optval); } else { *((int *)optval) = socket_handle->saved_error; } } } return(ret); }