summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_socket.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2015-06-15 18:29:56 +0200
committerCorinna Vinschen <corinna@vinschen.de>2015-06-15 18:29:56 +0200
commit79d65a1ed2eccd7c9c280895b8dc99ff7112b3c0 (patch)
treed15728d384376566f2a40feeb5eaca6195431e6a /winsup/cygwin/fhandler_socket.cc
parent6f9e2f3ed5ee1364dab6a47c604a6d7d370aab5c (diff)
downloadcygnal-79d65a1ed2eccd7c9c280895b8dc99ff7112b3c0.tar.gz
cygnal-79d65a1ed2eccd7c9c280895b8dc99ff7112b3c0.tar.bz2
cygnal-79d65a1ed2eccd7c9c280895b8dc99ff7112b3c0.zip
Try to handle concurrent close on socket more gracefully
* fhandler_socket.cc (LOCK_EVENTS): Don't enter critical section with invalid mutex handle since then socket has been closed. (UNLOCK_EVENTS): Close critical section. (fhandler_socket::evaluate_events): Handle calling connect on shutdown socket. (fhandler_socket::wait_for_events): Try for pthread_testcancel in case of WAIT_FAILED. Try to come up with a better errno in case we waited on an invalid handle. (fhandler_socket::release_events): Change wsock_mtx and wsock_evt to NULL under lock to avoid accessing invalid handle. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Diffstat (limited to 'winsup/cygwin/fhandler_socket.cc')
-rw-r--r--winsup/cygwin/fhandler_socket.cc54
1 files changed, 40 insertions, 14 deletions
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 1b28e5220..48f9aeb87 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -501,8 +501,14 @@ fhandler_socket::af_local_set_secret (char *buf)
counted as one socket. */
#define NUM_SOCKS (32768 / sizeof (wsa_event))
-#define LOCK_EVENTS WaitForSingleObject (wsock_mtx, INFINITE)
-#define UNLOCK_EVENTS ReleaseMutex (wsock_mtx)
+#define LOCK_EVENTS \
+ if (wsock_mtx && \
+ WaitForSingleObject (wsock_mtx, INFINITE) != WAIT_FAILED) \
+ {
+
+#define UNLOCK_EVENTS \
+ ReleaseMutex (wsock_mtx); \
+ }
static wsa_event wsa_events[NUM_SOCKS] __attribute__((section (".cygwin_dll_common"), shared));
@@ -709,14 +715,21 @@ fhandler_socket::evaluate_events (const long event_mask, long &events,
wsock_events->events &= ~FD_CONNECT;
wsock_events->connect_errorcode = 0;
}
- /* This test makes the accept function behave as on Linux when
- accept is called on a socket for which shutdown for the read side
- has been called. The second half of this code is in the shutdown
- method. See there for more info. */
- if ((event_mask & FD_ACCEPT) && (events & FD_CLOSE))
+ /* This test makes accept/connect behave as on Linux when accept/connect
+ is called on a socket for which shutdown has been called. The second
+ half of this code is in the shutdown method. */
+ if (events & FD_CLOSE)
{
- WSASetLastError (WSAEINVAL);
- ret = SOCKET_ERROR;
+ if ((event_mask & FD_ACCEPT) && saw_shutdown_read ())
+ {
+ WSASetLastError (WSAEINVAL);
+ ret = SOCKET_ERROR;
+ }
+ if (event_mask & FD_CONNECT)
+ {
+ WSASetLastError (WSAECONNRESET);
+ ret = SOCKET_ERROR;
+ }
}
if (erase)
wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE));
@@ -750,7 +763,8 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
{
case WSA_WAIT_TIMEOUT:
pthread_testcancel ();
- /*FALLTHRU*/
+ break;
+
case WSA_WAIT_EVENT_0:
break;
@@ -761,19 +775,31 @@ fhandler_socket::wait_for_events (const long event_mask, const DWORD flags)
return SOCKET_ERROR;
default:
- WSASetLastError (WSAEFAULT);
+ pthread_testcancel ();
+ /* wsock_evt can be NULL. We're generating the same errno values
+ as for sockets on which shutdown has been called. */
+ if (WSAGetLastError () != WSA_INVALID_HANDLE)
+ WSASetLastError (WSAEFAULT);
+ else
+ WSASetLastError ((event_mask & FD_CONNECT) ? WSAECONNRESET
+ : WSAEINVAL);
return SOCKET_ERROR;
}
}
-
return ret;
}
void
fhandler_socket::release_events ()
{
- NtClose (wsock_evt);
- NtClose (wsock_mtx);
+ HANDLE evt = wsock_evt;
+ HANDLE mtx = wsock_mtx;
+
+ LOCK_EVENTS;
+ wsock_evt = wsock_mtx = NULL;
+ } ReleaseMutex (mtx); /* == UNLOCK_EVENTS, but note using local mtx here. */
+ NtClose (evt);
+ NtClose (mtx);
}
/* Called from net.cc:fdsock() if a freshly created socket is not