From 5e8d7527afc9dd1113ec6fbdcb091d87c6e32c1c Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 22 Sep 2009 14:27:57 +0000 Subject: [PATCH] * autoload.cc (WSARecv): Define. * fhandler_socket.cc (fhandler_socket::recv_internal): Call WSARecv instead of WSARecvFrom if no name parameter is given. Explain why. --- winsup/cygwin/ChangeLog | 6 ++++++ winsup/cygwin/autoload.cc | 1 + winsup/cygwin/fhandler_socket.cc | 28 ++++++++++++++++++++++------ 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 + + * 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 * 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) {