From 9869e006f3ac34d7bd67fb6327f3605725995abc Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 27 Jul 2006 09:11:38 +0000 Subject: [PATCH] * fhandler.h (class fhandler_socket): Remove prot_info_ptr. (fhandler_socket::fixup_before_fork_exec): Remove. (fhandler_socket::fixup_after_exec): Remove. (fhandler_socket::need_fixup_before): Remove. * fhandler_socket.cc (fhandler_socket::fhandler_socket): Drop initializing prot_info_ptr. Remove unused code. (fhandler_socket::~fhandler_socket): Drop free'ing prot_info_ptr. (struct wsa_event): Rename connect_errorcode to errorcode. (fhandler_socket::evaluate_events): Handle FD_CLOSE error condition as FD_CONNECT error condition, except, never reset an FD_CLOSE error condition. Always set FD_WRITE after successfully recorded FD_CONNECT. (fhandler_socket::fixup_before_fork_exec): Remove. (fhandler_socket::fixup_after_fork): Revert to using handle duplication. (fhandler_socket::fixup_after_exec): Remove. (fhandler_socket::dup): Revert to using handle duplication. (fhandler_socket::send_internal): Only call wait_for_events in case of WSAEWOULDBLOCK condition. (fhandler_socket::set_close_on_exec): Call fhandler_base::set_close_on_exec. * net.cc (fdsock): Just set socket to inheritable on non-NT. Don't call inc_need_fixup_before. * select.cc (peek_socket): Don't set except_ready on every FD_CLOSE, just on error. --- winsup/cygwin/ChangeLog | 26 ++++++ winsup/cygwin/fhandler.h | 4 - winsup/cygwin/fhandler_socket.cc | 139 +++++-------------------------- winsup/cygwin/net.cc | 15 ++-- winsup/cygwin/select.cc | 2 +- 5 files changed, 58 insertions(+), 128 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index c75a91d73..d3693c526 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,29 @@ +2006-07-27 Corinna Vinschen + + * fhandler.h (class fhandler_socket): Remove prot_info_ptr. + (fhandler_socket::fixup_before_fork_exec): Remove. + (fhandler_socket::fixup_after_exec): Remove. + (fhandler_socket::need_fixup_before): Remove. + * fhandler_socket.cc (fhandler_socket::fhandler_socket): Drop + initializing prot_info_ptr. Remove unused code. + (fhandler_socket::~fhandler_socket): Drop free'ing prot_info_ptr. + (struct wsa_event): Rename connect_errorcode to errorcode. + (fhandler_socket::evaluate_events): Handle FD_CLOSE error condition + as FD_CONNECT error condition, except, never reset an FD_CLOSE error + condition. Always set FD_WRITE after successfully recorded FD_CONNECT. + (fhandler_socket::fixup_before_fork_exec): Remove. + (fhandler_socket::fixup_after_fork): Revert to using handle duplication. + (fhandler_socket::fixup_after_exec): Remove. + (fhandler_socket::dup): Revert to using handle duplication. + (fhandler_socket::send_internal): Only call wait_for_events in case + of WSAEWOULDBLOCK condition. + (fhandler_socket::set_close_on_exec): Call + fhandler_base::set_close_on_exec. + * net.cc (fdsock): Just set socket to inheritable on non-NT. Don't + call inc_need_fixup_before. + * select.cc (peek_socket): Don't set except_ready on every FD_CLOSE, + just on error. + 2006-07-26 Brian ford * fhandler.cc (fhandler_base::read): Call get_readahead_into_buffer diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 6468560b3..7b9ba7e3b 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -418,7 +418,6 @@ class fhandler_socket: public fhandler_base void af_local_set_sockpair_cred (); private: - struct _WSAPROTOCOL_INFOA *prot_info_ptr; char *sun_path; struct status_flags { @@ -481,10 +480,7 @@ class fhandler_socket: public fhandler_base int dup (fhandler_base *child); void set_close_on_exec (bool val); - virtual void fixup_before_fork_exec (DWORD); void fixup_after_fork (HANDLE); - void fixup_after_exec (); - bool need_fixup_before () const {return true;} char *get_proc_fd_name (char *buf); select_record *select_read (select_record *s); diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index 63858206d..a6f760a9b 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -136,22 +136,10 @@ fhandler_socket::fhandler_socket () : status () { need_fork_fixup (true); - prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF, - sizeof (WSAPROTOCOL_INFOA)); -#if 0 - if (pc.is_fs_special ()) - { - fhandler_socket * fhs = (fhandler_socket *) fh; - fhs->set_addr_family (AF_LOCAL); - fhs->set_sun_path (posix_path); - } -#endif } fhandler_socket::~fhandler_socket () { - if (prot_info_ptr) - cfree (prot_info_ptr); if (sun_path) cfree (sun_path); } @@ -398,7 +386,7 @@ struct wsa_event { LONG serial_number; long events; - int connect_errorcode; + int errorcode; pid_t owner; }; @@ -520,7 +508,9 @@ fhandler_socket::evaluate_events (const long event_mask, long &events, LOCK_EVENTS; wsock_events->events |= evts.lNetworkEvents; if (evts.lNetworkEvents & FD_CONNECT) - wsock_events->connect_errorcode = evts.iErrorCode[FD_CONNECT_BIT]; + wsock_events->errorcode = evts.iErrorCode[FD_CONNECT_BIT]; + else if (evts.lNetworkEvents & FD_CLOSE) + wsock_events->errorcode = evts.iErrorCode[FD_CLOSE_BIT]; UNLOCK_EVENTS; if ((evts.lNetworkEvents & FD_OOB) && wsock_events->owner) kill (wsock_events->owner, SIGURG); @@ -530,16 +520,22 @@ fhandler_socket::evaluate_events (const long event_mask, long &events, LOCK_EVENTS; if ((events = (wsock_events->events & event_mask)) != 0) { - if (events & FD_CONNECT) + if (events & (FD_CONNECT | FD_CLOSE)) { int wsa_err = 0; - if ((wsa_err = wsock_events->connect_errorcode) != 0) + if ((wsa_err = wsock_events->errorcode) != 0) { WSASetLastError (wsa_err); ret = SOCKET_ERROR; } - wsock_events->connect_errorcode = 0; - wsock_events->events &= ~FD_CONNECT; + if (events & FD_CONNECT) + { + if (!wsock_events->errorcode) + wsock_events->events |= FD_WRITE; + wsock_events->events &= ~FD_CONNECT; + } + if (!(events & FD_CLOSE)) + wsock_events->errorcode = 0; } if (erase) wsock_events->events &= ~(events & ~(FD_WRITE | FD_CLOSE)); @@ -598,84 +594,29 @@ fhandler_socket::release_events () CloseHandle (wsock_mtx); } -void -fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id) -{ - if (!WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr)) - debug_printf ("WSADuplicateSocket went fine, sock %p, win_proc_id %d, prot_info_ptr %p", - get_socket (), win_proc_id, prot_info_ptr); - else - { - debug_printf ("WSADuplicateSocket error, sock %p, win_proc_id %d, prot_info_ptr %p", - get_socket (), win_proc_id, prot_info_ptr); - set_winsock_errno (); - } -} - void fhandler_socket::fixup_after_fork (HANDLE parent) { - SOCKET new_sock; - - debug_printf ("WSASocket begin, dwServiceFlags1=%d", - prot_info_ptr->dwServiceFlags1); - - if ((new_sock = WSASocketA (FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - FROM_PROTOCOL_INFO, - prot_info_ptr, 0, 0)) == INVALID_SOCKET) - { - debug_printf ("WSASocket error"); - set_io_handle ((HANDLE)INVALID_SOCKET); - set_winsock_errno (); - } - else - { - debug_printf ("WSASocket went fine new_sock %p, old_sock %p", new_sock, get_socket ()); - - /* Go figure! Even though the original socket was not inheritable, - the duplicated socket is inheritable again. This can lead to all - sorts of trouble, apparently. Note that there's no way to prevent - this on 9x, not even by trying to reset socket inheritance using - DuplicateHandle and closing the original socket. */ - if (wincap.has_set_handle_information ()) - SetHandleInformation ((HANDLE) new_sock, HANDLE_FLAG_INHERIT, 0); - - set_io_handle ((HANDLE) new_sock); - } - if (parent) /* fork, not exec or dup */ - { - fork_fixup (parent, wsock_mtx, "wsock_mtx"); - fork_fixup (parent, wsock_evt, "wsock_evt"); - } -} - -void -fhandler_socket::fixup_after_exec () -{ - if (!close_on_exec ()) - fixup_after_fork (NULL); + fork_fixup (parent, wsock_mtx, "wsock_mtx"); + fork_fixup (parent, wsock_evt, "wsock_evt"); + fhandler_base::fixup_after_fork (parent); } int fhandler_socket::dup (fhandler_base *child) { - HANDLE nh; - debug_printf ("here"); fhandler_socket *fhs = (fhandler_socket *) child; if (!DuplicateHandle (hMainProc, wsock_mtx, hMainProc, &fhs->wsock_mtx, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - system_printf ("DuplicateHandle(%x) failed, %E", wsock_mtx); __seterrno (); return -1; } if (!DuplicateHandle (hMainProc, wsock_evt, hMainProc, &fhs->wsock_evt, 0, TRUE, DUPLICATE_SAME_ACCESS)) { - system_printf ("DuplicateHandle(%x) failed, %E", wsock_evt); __seterrno (); CloseHandle (fhs->wsock_mtx); return -1; @@ -698,48 +639,13 @@ fhandler_socket::dup (fhandler_base *child) } } fhs->connect_state (connect_state ()); - - /* Since WSADuplicateSocket() fails on NT systems when the process - is currently impersonating a non-privileged account, we revert - to the original account before calling WSADuplicateSocket() and - switch back afterwards as it's also in fork(). - If WSADuplicateSocket() still fails for some reason, we fall back - to DuplicateHandle(). */ - WSASetLastError (0); - cygheap->user.deimpersonate (); - fhs->set_io_handle (get_io_handle ()); - fhs->fixup_before_fork_exec (GetCurrentProcessId ()); - cygheap->user.reimpersonate (); - if (!WSAGetLastError ()) + int ret = fhandler_base::dup (child); + if (ret) { - /* Call with NULL parent, otherwise wsock_mtx and wsock_evt are - duplicated again with wrong close_on_exec settings. */ - fhs->fixup_after_fork (NULL); - if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET) - { - cygheap->fdtab.inc_need_fixup_before (); - return 0; - } - } - debug_printf ("WSADuplicateSocket failed, trying DuplicateHandle"); - - /* We don't call fhandler_base::dup here since that requires - having winsock called from fhandler_base and it creates only - inheritable sockets which is wrong for winsock2. */ - - if (!DuplicateHandle (hMainProc, get_io_handle (), hMainProc, &nh, 0, - FALSE, DUPLICATE_SAME_ACCESS)) - { - system_printf ("DuplicateHandle(%x) failed, %E", get_io_handle ()); - __seterrno (); CloseHandle (fhs->wsock_evt); CloseHandle (fhs->wsock_mtx); - return -1; } - VerifyHandle (nh); - fhs->set_io_handle (nh); - cygheap->fdtab.inc_need_fixup_before (); - return 0; + return ret; } int __stdcall @@ -1379,7 +1285,8 @@ fhandler_socket::send_internal (struct _WSABUF *wsabuf, DWORD wsacnt, int flags, wsock_events->events &= ~FD_WRITE; UNLOCK_EVENTS; } - while (res && err && !(res = wait_for_events (FD_WRITE | FD_CLOSE))); + while (res && err == WSAEWOULDBLOCK + && !(res = wait_for_events (FD_WRITE | FD_CLOSE))); if (res == SOCKET_ERROR) set_winsock_errno (); @@ -1682,7 +1589,7 @@ fhandler_socket::set_close_on_exec (bool val) { set_no_inheritance (wsock_mtx, val); set_no_inheritance (wsock_evt, val); - close_on_exec (val); + fhandler_base::set_close_on_exec (val); debug_printf ("set close_on_exec for %s to %d", get_name (), val); } diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc index 80f34a886..87a413556 100644 --- a/winsup/cygwin/net.cc +++ b/winsup/cygwin/net.cc @@ -501,14 +501,16 @@ cygwin_getprotobynumber (int number) bool fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc) { - if (wincap.has_set_handle_information ()) + /* NT systems apparently set sockets to inheritable by default */ + if (!wincap.has_set_handle_information () + && !DuplicateHandle (hMainProc, (HANDLE) soc, + hMainProc, (HANDLE *) &soc, + 0, TRUE, + DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE)) { - /* NT systems apparently set sockets to inheritable by default */ - SetHandleInformation ((HANDLE) soc, HANDLE_FLAG_INHERIT, 0); - debug_printf ("reset socket inheritance"); + debug_printf ("set socket inheritance failed, %E"); + return false; } - else - debug_printf ("not setting socket inheritance"); fd = build_fh_dev (*dev); if (!fd.isopen ()) return false; @@ -517,7 +519,6 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc) return false; fd->set_flags (O_RDWR | O_BINARY); fd->uninterruptible_io (true); - cygheap->fdtab.inc_need_fixup_before (); debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc); #if 0 /* Same default buffer sizes as on Linux (instead of WinSock default 8K). diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index a1abba610..abfe9e5a3 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -1279,7 +1279,7 @@ peek_socket (select_record *me, bool) me->write_ready |= !!(events & (FD_WRITE | FD_CLOSE)); } if (me->except_selected) - me->except_ready |= ret || !!(events & (FD_OOB | FD_CLOSE)); + me->except_ready |= ret || !!(events & FD_OOB); return me->read_ready || me->write_ready || me->except_ready; }