diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2009-11-17 10:43:01 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2009-11-17 10:43:01 +0000 |
commit | b14f53a8ec619146e20cae8831dec4a8d9aaf883 (patch) | |
tree | 029928c686817a409f1665db3eb5a381f411f819 /winsup/cygwin/fhandler_socket.cc | |
parent | 88242190ec6f016a5a7956bd20a844dd38e436e6 (diff) | |
download | cygnal-b14f53a8ec619146e20cae8831dec4a8d9aaf883.tar.gz cygnal-b14f53a8ec619146e20cae8831dec4a8d9aaf883.tar.bz2 cygnal-b14f53a8ec619146e20cae8831dec4a8d9aaf883.zip |
Reintegrate socket duplication via WSADuplicateSocket/WSASocket.
* autoload.cc (WSADuplicateSocketW): Define.
(WSASocketW): Define.
* dtable.cc (dtable::release): Call dec_need_fixup_before if necessary.
(dtable::fixup_before_fork): New function.
(dtable::fixup_before_exec): New function.
* dtable.h (class dtable): Add member cnt_need_fixup_before. Add
declarations for above new functions.
(dtable::dec_need_fixup_before): New inline method.
(dtable::inc_need_fixup_before): New inline method.
(dtable::need_fixup_before): New inline method.
* fhandler.h (fhandler_base::fixup_before_fork_exec): New virtual
method.
(fhandler_base::need_fixup_before): New virtual method.
(class fhandler_socket): Add member prot_info_ptr.
(fhandler_socket::init_fixup_before): Declare.
(fhandler_socket::need_fixup_before): New inline method.
(fhandler_socket::fixup_before_fork_exec): Declare.
(fhandler_socket::fixup_after_exec): Declare.
* fhandler_socket.cc (fhandler_socket::fhandler_socket): Initialize
prot_info_ptr to NULL.
(fhandler_socket::~fhandler_socket): Free prot_info_ptr conditionally.
(fhandler_socket::init_fixup_before): New method.
(fhandler_socket::fixup_before_fork_exec): Ditto.
(fhandler_socket::fixup_after_fork): Use WSASocketW to duplicate
socket if necessary.
(fhandler_socket::fixup_after_exec): New method.
(fhandler_socket::dup): Use fixup_before_fork_exec/fixup_after_fork
to duplicate socket if necessary.
* fork.cc (frok::parent): Start child suspended if some fhandler
needs fixup before fork. If so, call dtable::fixup_before_fork after
CreateProcess and resume child.
* net.cc (fdsock): Try to find out if socket needs fixup before and
initialize socket accordingly. Add HUGE comment to explain what happens
and why.
* spawn.cc (spawn_guts): Start child suspended if some fhandler needs
fixup before exec. If so, call dtable::fixup_before_exec after
CreateProcess.
Diffstat (limited to 'winsup/cygwin/fhandler_socket.cc')
-rw-r--r-- | winsup/cygwin/fhandler_socket.cc | 85 |
1 files changed, 79 insertions, 6 deletions
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc index a1cfce30f..6a6620686 100644 --- a/winsup/cygwin/fhandler_socket.cc +++ b/winsup/cygwin/fhandler_socket.cc @@ -151,6 +151,7 @@ fhandler_socket::fhandler_socket () : wsock_events (NULL), wsock_mtx (NULL), wsock_evt (NULL), + prot_info_ptr (NULL), sun_path (NULL), peer_sun_path (NULL), status () @@ -160,6 +161,8 @@ fhandler_socket::fhandler_socket () : fhandler_socket::~fhandler_socket () { + if (prot_info_ptr) + cfree (prot_info_ptr); if (sun_path) cfree (sun_path); if (peer_sun_path) @@ -631,12 +634,62 @@ fhandler_socket::release_events () NtClose (wsock_mtx); } +/* Called from net.cc:fdsock() if a freshly created socket is not + inheritable. In that case we use fixup_before_fork_exec. See + the comment in fdsock() for a description of the problem. */ +void +fhandler_socket::init_fixup_before () +{ + prot_info_ptr = (LPWSAPROTOCOL_INFOW) + cmalloc_abort (HEAP_BUF, sizeof (WSAPROTOCOL_INFOW)); + cygheap->fdtab.inc_need_fixup_before (); +} + +int +fhandler_socket::fixup_before_fork_exec (DWORD win_pid) +{ + SOCKET ret = WSADuplicateSocketW (get_socket (), win_pid, prot_info_ptr); + if (ret) + set_winsock_errno (); + else + debug_printf ("WSADuplicateSocket succeeded"); + return (int) ret; +} + void fhandler_socket::fixup_after_fork (HANDLE parent) { fork_fixup (parent, wsock_mtx, "wsock_mtx"); fork_fixup (parent, wsock_evt, "wsock_evt"); - fhandler_base::fixup_after_fork (parent); + + if (!need_fixup_before ()) + { + fhandler_base::fixup_after_fork (parent); + return; + } + + SOCKET new_sock = WSASocketW (FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, prot_info_ptr, 0, 0); + if (new_sock == INVALID_SOCKET) + { + set_winsock_errno (); + set_io_handle ((HANDLE) INVALID_SOCKET); + } + else + { + /* Even though the original socket was not inheritable, the duplicated + socket is potentially inheritable again. */ + SetHandleInformation ((HANDLE) new_sock, HANDLE_FLAG_INHERIT, 0); + set_io_handle ((HANDLE) new_sock); + debug_printf ("WSASocket succeeded"); + } +} + +void +fhandler_socket::fixup_after_exec () +{ + if (need_fixup_before () && !close_on_exec ()) + fixup_after_fork (NULL); } int @@ -679,13 +732,33 @@ fhandler_socket::dup (fhandler_base *child) } } fhs->connect_state (connect_state ()); - int ret = fhandler_base::dup (child); - if (ret) + + if (!need_fixup_before ()) { - NtClose (fhs->wsock_evt); - NtClose (fhs->wsock_mtx); + int ret = fhandler_base::dup (child); + if (ret) + { + NtClose (fhs->wsock_evt); + NtClose (fhs->wsock_mtx); + } + return ret; } - return ret; + + cygheap->user.deimpersonate (); + fhs->init_fixup_before (); + fhs->set_io_handle (get_io_handle ()); + if (!fhs->fixup_before_fork_exec (GetCurrentProcessId ())) + { + cygheap->user.reimpersonate (); + fhs->fixup_after_fork (hMainProc); + if (fhs->get_io_handle() != (HANDLE) INVALID_SOCKET) + return 0; + } + cygheap->user.reimpersonate (); + cygheap->fdtab.dec_need_fixup_before (); + NtClose (fhs->wsock_evt); + NtClose (fhs->wsock_mtx); + return -1; } int __stdcall |