summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog6
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/fhandler_socket.cc28
3 files changed, 29 insertions, 6 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 9752abe5e..b09bf6fa7 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,9 @@
+2009-09-22 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc (WSARecv): Define.
+ * fhandler_socket.cc (fhandler_socket::recv_internal): Call WSARecv
+ instead of WSARecvFrom if no name parameter is given. Explain why.
+
2009-09-22 Eric Blake <ebb9@byu.net>
* syscalls.cc (faccessat): Fix typo, reject bad flags.
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index afe6028a5..942891303 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -391,6 +391,7 @@ LoadDLLfunc (WSAEnumNetworkEvents, 12, ws2_32)
LoadDLLfunc (WSAEventSelect, 12, ws2_32)
LoadDLLfunc (WSAGetLastError, 0, ws2_32)
LoadDLLfunc (WSAIoctl, 36, ws2_32)
+LoadDLLfunc (WSARecv, 28, ws2_32)
LoadDLLfunc (WSARecvFrom, 36, ws2_32)
LoadDLLfunc (WSASendMsg, 24, ws2_32)
LoadDLLfunc (WSASendTo, 36, ws2_32)
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 52d03ed07..3e218347d 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -1379,14 +1379,30 @@ fhandler_socket::recv_internal (LPWSAMSG wsamsg)
{
if (use_recvmsg)
res = WSARecvMsg (get_socket (), wsamsg, &wret, NULL, NULL);
+ /* This is working around a really weird problem in WinSock.
+
+ Assume you create a socket, fork the process (thus duplicating
+ the socket), connect the socket in the child, then call recv
+ on the original socket handle in the parent process.
+ In this scenario, calls to WinSock's recvfrom and WSARecvFrom
+ in the parent will fail with WSAEINVAL, regardless whether both
+ address parameters, name and namelen, are NULL or point to valid
+ storage. However, calls to recv and WSARecv succeed as expected.
+ Per MSDN, WSAEINVAL in the context of recv means "The socket has not
+ been bound". It is as if the recvfrom functions test if the socket
+ is bound locally, but in the parent process, WinSock doesn't know
+ about that and fails, while the same test is omitted in the recv
+ functions.
+
+ This also covers another weird case: Winsock returns WSAEFAULT if
+ namelen is a valid pointer while name is NULL. Both parameters are
+ ignored for TCP sockets, so this only occurs when using UDP socket. */
+ else if (!wsamsg->name)
+ res = WSARecv (get_socket (), wsabuf, wsacnt, &wret, &wsamsg->dwFlags,
+ NULL, NULL);
else
res = WSARecvFrom (get_socket (), wsabuf, wsacnt, &wret,
- &wsamsg->dwFlags, wsamsg->name,
- /* Winsock returns WSAEFAULT if namelen is a valid
- pointer while name is NULL. Both parameters are
- ignored for TCP sockets, so this only occurs when
- using UDP socket. */
- wsamsg->name ? &wsamsg->namelen : NULL,
+ &wsamsg->dwFlags, wsamsg->name, &wsamsg->namelen,
NULL, NULL);
if (!res)
{