diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 74068075f..9a3aa3e8c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2012-08-01 Corinna Vinschen + + * fhandler.h (fhandler_socket::recv_internal): Add bool parameter. + Add regparm attribute. + * fhandler_socket.cc (fhandler_socket::read): Call recv_internal with + second parameter set to false. + (fhandler_socket::readv): Ditto. + (fhandler_socket::recvfrom): Ditto. + (fhandler_socket::recv_internal): Convert use_recvmsg from local + variable to parameter. Use as request for using WSARecvMsg. Only + fail if WSARecvMsg can't be loaded and wsamsg->Control.len > 0, + otherwise use WSARecv{From}. Restrict dwFlags to MSG_PEEK when using + WSARecvMsg. + (fhandler_socket::recvmsg): Prefer using WSARecvMsg. Change priority + of tests for not using WSARecvMsg. Call recv_internal with second + parameter set accordingly. + 2012-08-01 Corinna Vinschen * Makefile.in: Semi-revert patch from 2012-07-01, assuming the previous diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 9f30f5cc0..39e1e7573 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -558,7 +558,7 @@ class fhandler_socket: public fhandler_base int open (int flags, mode_t mode = 0); void __stdcall read (void *ptr, size_t& len) __attribute__ ((regparm (3))); ssize_t __stdcall readv (const struct iovec *, int iovcnt, ssize_t tot = -1); - inline ssize_t recv_internal (struct _WSAMSG *wsamsg); + inline ssize_t recv_internal (struct _WSAMSG *wsamsg, bool use_recvmsg) __attribute__ ((regparm (3))); ssize_t recvfrom (void *ptr, size_t len, int flags, struct sockaddr *from, int *fromlen); ssize_t recvmsg (struct msghdr *msg, int flags); diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 054eafea1..a11c7efbe 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -1330,7 +1330,7 @@ fhandler_socket::read (void *in_ptr, size_t& len) { WSABUF wsabuf = { len, (char *) in_ptr }; WSAMSG wsamsg = { NULL, 0, &wsabuf, 1, { 0, NULL }, 0 }; - len = recv_internal (&wsamsg); + len = recv_internal (&wsamsg, false); } int @@ -1346,7 +1346,7 @@ fhandler_socket::readv (const struct iovec *const iov, const int iovcnt, wsaptr->buf = (char *) iovptr->iov_base; } WSAMSG wsamsg = { NULL, 0, wsabuf, iovcnt, { 0, NULL}, 0 }; - return recv_internal (&wsamsg); + return recv_internal (&wsamsg, false); } extern "C" { @@ -1375,28 +1375,32 @@ get_ext_funcptr (SOCKET sock, void *funcptr) } inline ssize_t -fhandler_socket::recv_internal (LPWSAMSG wsamsg) +fhandler_socket::recv_internal (LPWSAMSG wsamsg, bool use_recvmsg) { ssize_t res = 0; DWORD ret = 0, wret; int evt_mask = FD_READ | ((wsamsg->dwFlags & MSG_OOB) ? FD_OOB : 0); LPWSABUF &wsabuf = wsamsg->lpBuffers; ULONG &wsacnt = wsamsg->dwBufferCount; - bool use_recvmsg = false; static NO_COPY LPFN_WSARECVMSG WSARecvMsg; DWORD wait_flags = wsamsg->dwFlags; bool waitall = !!(wait_flags & MSG_WAITALL); wsamsg->dwFlags &= (MSG_OOB | MSG_PEEK | MSG_DONTROUTE); - if (wsamsg->Control.len > 0) + if (use_recvmsg) { if (!WSARecvMsg && get_ext_funcptr (get_socket (), &WSARecvMsg) == SOCKET_ERROR) { - set_winsock_errno (); - return SOCKET_ERROR; + if (wsamsg->Control.len > 0) + { + set_winsock_errno (); + return SOCKET_ERROR; + } + use_recvmsg = false; } - use_recvmsg = true; + else /* Only MSG_PEEK is supported by WSARecvMsg. */ + wsamsg->dwFlags &= MSG_PEEK; } if (waitall) { @@ -1503,7 +1507,7 @@ fhandler_socket::recvfrom (void *ptr, size_t len, int flags, &wsabuf, 1, { 0, NULL}, flags }; - ssize_t ret = recv_internal (&wsamsg); + ssize_t ret = recv_internal (&wsamsg, false); if (fromlen) *fromlen = wsamsg.namelen; return ret; @@ -1518,12 +1522,12 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags) /* Disappointing but true: Even if WSARecvMsg is supported, it's only supported for datagram and raw sockets. */ - if (!wincap.has_recvmsg () || get_socket_type () == SOCK_STREAM - || get_addr_family () == AF_LOCAL) + bool use_recvmsg = true; + if (get_socket_type () == SOCK_STREAM || get_addr_family () == AF_LOCAL + || !wincap.has_recvmsg ()) { + use_recvmsg = false; msg->msg_controllen = 0; - if (!CYGWIN_VERSION_CHECK_FOR_USING_ANCIENT_MSGHDR) - msg->msg_flags = 0; } WSABUF wsabuf[msg->msg_iovlen]; @@ -1538,7 +1542,7 @@ fhandler_socket::recvmsg (struct msghdr *msg, int flags) wsabuf, msg->msg_iovlen, { msg->msg_controllen, (char *) msg->msg_control }, flags }; - ssize_t ret = recv_internal (&wsamsg); + ssize_t ret = recv_internal (&wsamsg, use_recvmsg); if (ret >= 0) { msg->msg_namelen = wsamsg.namelen;