* autoload.cc (WSARecv): Define.

* fhandler_socket.cc (fhandler_socket::recv_internal): Call WSARecv
	instead of WSARecvFrom if no name parameter is given.  Explain why.
This commit is contained in:
Corinna Vinschen 2009-09-22 14:27:57 +00:00
parent 74a67d01a5
commit 5e8d7527af
3 changed files with 29 additions and 6 deletions

View File

@ -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.

View File

@ -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)

View File

@ -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)
{