diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c16bc32ad..5805b6ae0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,20 @@ +2009-07-01 Corinna Vinschen + + * fhandler.h (class fhandler_socket): Add class members and methods + to store and retrieve the SO_RCVBUF and SO_SNDBUF sizes. + * fhandler_socket.cc (fhandler_socket::dup): Duplicate new members. + (fhandler_socket::send_internal): Check for SO_SNDBUF size and + restrict send to 1 byte less per KB 823764. Leave loop immediately + if WSASendMsg has been used. + * net.cc (fdsock): Change comment again. Set buffer sizes to 65536. + Store values in fhandler_socket. + (cygwin_setsockopt): Store SO_RCVBUF and SO_SNDBUF sizes in + fhandler_socket. + (cygwin_sendto): Drop call to sig_dispatch_pending. + (cygwin_recvfrom): Ditto. + (cygwin_recvmsg): Ditto. + (cygwin_sendmsg): Ditto. + 2009-06-30 Christopher Faylor * select.h: New file split from fhandler.h. diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 425746f0b..51a68a090 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -445,6 +445,15 @@ class fhandler_socket: public fhandler_base int af_local_connect (); void af_local_set_sockpair_cred (); + private: + int _rmem; + int _wmem; + public: + int &rmem () { return _rmem; } + int &wmem () { return _wmem; } + void rmem (int nrmem) { _rmem = nrmem; } + void wmem (int nwmem) { _wmem = nwmem; } + private: char *sun_path; struct status_flags diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 17900fdfe..ea057d699 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -657,6 +657,8 @@ fhandler_socket::dup (fhandler_base *child) } fhs->wsock_events = wsock_events; + fhs->rmem (rmem ()); + fhs->wmem (wmem ()); fhs->addr_family = addr_family; fhs->set_socket_type (get_socket_type ()); if (get_addr_family () == AF_LOCAL) @@ -1487,10 +1489,15 @@ fhandler_socket::send_internal (struct _WSAMSG *wsamsg, int flags) for (DWORD i = 0; i < wsamsg->dwBufferCount; off >= wsamsg->lpBuffers[i].len && (++i, off = 0)) { - buf.buf = wsamsg->lpBuffers[i].buf + off; - buf.len = wsamsg->lpBuffers[i].len - off; - if (buf.len > 65520) /* See net.cc:fdsock() and MSDN KB 823764 */ - buf.len = 65520; + /* FIXME? Use the same technique in call to WSASendMsg? */ + if (!use_sendmsg) + { + buf.buf = wsamsg->lpBuffers[i].buf + off; + buf.len = wsamsg->lpBuffers[i].len - off; + /* See net.cc:fdsock() and MSDN KB 823764 */ + if (buf.len >= (unsigned) wmem ()) + buf.len = (unsigned) wmem () - 1; + } do { @@ -1513,6 +1520,8 @@ fhandler_socket::send_internal (struct _WSAMSG *wsamsg, int flags) { off += ret; sum += ret; + if (use_sendmsg) + break; } else if (is_nonblocking () || err != WSAEWOULDBLOCK) break; diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index bf982b317..393e2a998 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -495,18 +495,25 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc) /* Raise default buffer sizes (instead of WinSock default 8K). + 64K appear to have the best size/performance ratio for a default + value. Tested with ssh/scp on Vista over Gigabit LAN. + NOTE. If the SO_RCVBUF size exceeds 65535(*), and if the socket is - connected to a remote machine, then duplicating the socket on fork/exec - fails with WinSock error 10022, WSAEINVAL. An explanation for this - weird behaviour would be nice. + connected to a remote machine, then calling WSADuplicateSocket on + fork/exec fails with WinSock error 10022, WSAEINVAL. Fortunately + we don't use WSADuplicateSocket anymore, rather we just utilize + handle inheritance. An explanation for this weird behaviour would + be nice, though. (*) Maximum normal TCP window size. Coincidence? */ - int rmem = 65520; - int wmem = 65520; - if (::setsockopt (soc, SOL_SOCKET, SO_RCVBUF, (char *) &rmem, sizeof (int))) + ((fhandler_socket *) fd)->rmem () = 65536; + ((fhandler_socket *) fd)->wmem () = 65536; + if (::setsockopt (soc, SOL_SOCKET, SO_RCVBUF, + (char *) &((fhandler_socket *) fd)->rmem (), sizeof (int))) debug_printf ("setsockopt(SO_RCVBUF) failed, %lu", WSAGetLastError ()); - if (::setsockopt (soc, SOL_SOCKET, SO_SNDBUF, (char *) &wmem, sizeof (int))) + if (::setsockopt (soc, SOL_SOCKET, SO_SNDBUF, + (char *) &((fhandler_socket *) fd)->wmem (), sizeof (int))) debug_printf ("setsockopt(SO_SNDBUF) failed, %lu", WSAGetLastError ()); return true; @@ -560,7 +567,6 @@ cygwin_sendto (int fd, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) { int res; - sig_dispatch_pending (); fhandler_socket *fh = get (fd); @@ -582,7 +588,6 @@ cygwin_recvfrom (int fd, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen) { int res; - sig_dispatch_pending (); fhandler_socket *fh = get (fd); @@ -683,8 +688,21 @@ cygwin_setsockopt (int fd, int level, int optname, const void *optval, else set_winsock_errno (); } - else if (level == SOL_SOCKET && optname == SO_REUSEADDR) - fh->saw_reuseaddr (*(int *) optval); + else if (level == SOL_SOCKET) + switch (optname) + { + case SO_REUSEADDR: + fh->saw_reuseaddr (*(int *) optval); + break; + case SO_RCVBUF: + fh->rmem (*(int *) optval); + break; + case SO_SNDBUF: + fh->wmem (*(int *) optval); + break; + default: + break; + } } syscall_printf ("%d = setsockopt (%d, %d, %x, %p, %d)", @@ -2901,7 +2919,6 @@ extern "C" int cygwin_recvmsg (int fd, struct msghdr *msg, int flags) { int res; - sig_dispatch_pending (); fhandler_socket *fh = get (fd); @@ -2924,7 +2941,6 @@ extern "C" int cygwin_sendmsg (int fd, const struct msghdr *msg, int flags) { int res; - sig_dispatch_pending (); fhandler_socket *fh = get (fd);