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.
This commit is contained in:
		| @@ -1,3 +1,44 @@ | |||||||
|  | 2009-11-17  Corinna Vinschen  <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	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. | ||||||
|  |  | ||||||
| 2009-11-16  Eric Blake  <ebb9@byu.net> | 2009-11-16  Eric Blake  <ebb9@byu.net> | ||||||
|  |  | ||||||
| 	* environ.cc (setenv): Detect invalid argument. | 	* environ.cc (setenv): Detect invalid argument. | ||||||
|   | |||||||
| @@ -387,6 +387,7 @@ LoadDLLfunc (setsockopt, 20, ws2_32) | |||||||
| LoadDLLfunc (shutdown, 8, ws2_32) | LoadDLLfunc (shutdown, 8, ws2_32) | ||||||
| LoadDLLfunc (socket, 12, ws2_32) | LoadDLLfunc (socket, 12, ws2_32) | ||||||
| LoadDLLfunc (WSAAsyncSelect, 16, ws2_32) | LoadDLLfunc (WSAAsyncSelect, 16, ws2_32) | ||||||
|  | LoadDLLfunc (WSADuplicateSocketW, 12, ws2_32) | ||||||
| LoadDLLfunc (WSAEnumNetworkEvents, 12, ws2_32) | LoadDLLfunc (WSAEnumNetworkEvents, 12, ws2_32) | ||||||
| LoadDLLfunc (WSAEventSelect, 12, ws2_32) | LoadDLLfunc (WSAEventSelect, 12, ws2_32) | ||||||
| LoadDLLfunc (WSAGetLastError, 0, ws2_32) | LoadDLLfunc (WSAGetLastError, 0, ws2_32) | ||||||
| @@ -396,6 +397,7 @@ LoadDLLfunc (WSARecvFrom, 36, ws2_32) | |||||||
| LoadDLLfunc (WSASendMsg, 24, ws2_32) | LoadDLLfunc (WSASendMsg, 24, ws2_32) | ||||||
| LoadDLLfunc (WSASendTo, 36, ws2_32) | LoadDLLfunc (WSASendTo, 36, ws2_32) | ||||||
| LoadDLLfunc (WSASetLastError, 4, ws2_32) | LoadDLLfunc (WSASetLastError, 4, ws2_32) | ||||||
|  | LoadDLLfunc (WSASocketW, 24, ws2_32) | ||||||
| // LoadDLLfunc (WSAStartup, 8, ws2_32) | // LoadDLLfunc (WSAStartup, 8, ws2_32) | ||||||
| LoadDLLfunc (WSAWaitForMultipleEvents, 20, ws2_32) | LoadDLLfunc (WSAWaitForMultipleEvents, 20, ws2_32) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -248,6 +248,8 @@ dtable::release (int fd) | |||||||
| { | { | ||||||
|   if (!not_open (fd)) |   if (!not_open (fd)) | ||||||
|     { |     { | ||||||
|  |       if (fds[fd]->need_fixup_before ()) | ||||||
|  | 	dec_need_fixup_before (); | ||||||
|       fhandler_base *arch = fds[fd]->archetype; |       fhandler_base *arch = fds[fd]->archetype; | ||||||
|       delete fds[fd]; |       delete fds[fd]; | ||||||
|       if (arch && !arch->usecount) |       if (arch && !arch->usecount) | ||||||
| @@ -1020,3 +1022,31 @@ handle_to_fn (HANDLE h, char *posix_fn) | |||||||
|   strcpy (posix_fn,  unknown_file); |   strcpy (posix_fn,  unknown_file); | ||||||
|   return false; |   return false; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | dtable::fixup_before_fork (DWORD target_proc_id) | ||||||
|  | { | ||||||
|  |   lock (); | ||||||
|  |   fhandler_base *fh; | ||||||
|  |   for (size_t i = 0; i < size; i++) | ||||||
|  |     if ((fh = fds[i]) != NULL) | ||||||
|  |       { | ||||||
|  |         debug_printf ("fd %d (%s)", i, fh->get_name ()); | ||||||
|  |         fh->fixup_before_fork_exec (target_proc_id); | ||||||
|  |       } | ||||||
|  |   unlock (); | ||||||
|  | }  | ||||||
|  | void | ||||||
|  | dtable::fixup_before_exec (DWORD target_proc_id) | ||||||
|  | { | ||||||
|  |   lock (); | ||||||
|  |   fhandler_base *fh; | ||||||
|  |   for (size_t i = 0; i < size; i++) | ||||||
|  |     if ((fh = fds[i]) != NULL && !fh->close_on_exec ()) | ||||||
|  |       { | ||||||
|  |         debug_printf ("fd %d (%s)", i, fh->get_name ()); | ||||||
|  |         fh->fixup_before_fork_exec (target_proc_id); | ||||||
|  |       } | ||||||
|  |   unlock (); | ||||||
|  | }  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -31,14 +31,22 @@ class dtable | |||||||
|   unsigned farchetype; |   unsigned farchetype; | ||||||
|   static const int initial_archetype_size = 8; |   static const int initial_archetype_size = 8; | ||||||
|   int first_fd_for_open; |   int first_fd_for_open; | ||||||
|  |   int cnt_need_fixup_before; | ||||||
|   void lock () {lock_process::locker.acquire ();} |   void lock () {lock_process::locker.acquire ();} | ||||||
|   void unlock () {lock_process::locker.release ();} |   void unlock () {lock_process::locker.release ();} | ||||||
| public: | public: | ||||||
|   size_t size; |   size_t size; | ||||||
|  |  | ||||||
|   dtable () : archetypes (NULL), narchetypes (0), farchetype (0), first_fd_for_open(3) {} |   dtable () : archetypes (NULL), narchetypes (0), farchetype (0), first_fd_for_open(3), cnt_need_fixup_before(0) {} | ||||||
|   void init () {first_fd_for_open = 3;} |   void init () {first_fd_for_open = 3;} | ||||||
|  |  | ||||||
|  |   void dec_need_fixup_before () | ||||||
|  |     { if (cnt_need_fixup_before > 0) --cnt_need_fixup_before; } | ||||||
|  |   void inc_need_fixup_before () | ||||||
|  |     { cnt_need_fixup_before++; } | ||||||
|  |   bool need_fixup_before () | ||||||
|  |     { return cnt_need_fixup_before > 0; } | ||||||
|  |  | ||||||
|   void move_fd (int, int); |   void move_fd (int, int); | ||||||
|   int vfork_child_dup (); |   int vfork_child_dup (); | ||||||
|   void vfork_parent_restore (); |   void vfork_parent_restore (); | ||||||
| @@ -73,6 +81,8 @@ public: | |||||||
|   fhandler_base *find_archetype (device& dev); |   fhandler_base *find_archetype (device& dev); | ||||||
|   fhandler_base **add_archetype (); |   fhandler_base **add_archetype (); | ||||||
|   void delete_archetype (fhandler_base *); |   void delete_archetype (fhandler_base *); | ||||||
|  |   void fixup_before_exec (DWORD win_proc_id); | ||||||
|  |   void fixup_before_fork (DWORD win_proc_id); | ||||||
|   friend void dtable_init (); |   friend void dtable_init (); | ||||||
|   friend void __stdcall close_all_files (bool); |   friend void __stdcall close_all_files (bool); | ||||||
|   friend class fhandler_disk_file; |   friend class fhandler_disk_file; | ||||||
|   | |||||||
| @@ -226,6 +226,7 @@ class fhandler_base | |||||||
|       return close_on_exec () ? &sec_none_nih : &sec_none; |       return close_on_exec () ? &sec_none_nih : &sec_none; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   virtual int fixup_before_fork_exec (DWORD) { return 0; } | ||||||
|   virtual void fixup_after_fork (HANDLE); |   virtual void fixup_after_fork (HANDLE); | ||||||
|   virtual void fixup_after_exec (); |   virtual void fixup_after_exec (); | ||||||
|   void create_read_state (LONG n) |   void create_read_state (LONG n) | ||||||
| @@ -270,6 +271,7 @@ class fhandler_base | |||||||
|  |  | ||||||
|   /* fixup fd possibly non-inherited handles after fork */ |   /* fixup fd possibly non-inherited handles after fork */ | ||||||
|   bool fork_fixup (HANDLE, HANDLE &, const char *); |   bool fork_fixup (HANDLE, HANDLE &, const char *); | ||||||
|  |   virtual bool need_fixup_before () const {return false;} | ||||||
|  |  | ||||||
|   virtual int open (int, mode_t = 0); |   virtual int open (int, mode_t = 0); | ||||||
|   int open_fs (int, mode_t = 0); |   int open_fs (int, mode_t = 0); | ||||||
| @@ -463,6 +465,12 @@ class fhandler_socket: public fhandler_base | |||||||
|   void rmem (int nrmem) { _rmem = nrmem; } |   void rmem (int nrmem) { _rmem = nrmem; } | ||||||
|   void wmem (int nwmem) { _wmem = nwmem; } |   void wmem (int nwmem) { _wmem = nwmem; } | ||||||
|  |  | ||||||
|  |  private: | ||||||
|  |   struct _WSAPROTOCOL_INFOW *prot_info_ptr; | ||||||
|  |  public: | ||||||
|  |   void init_fixup_before (); | ||||||
|  |   bool need_fixup_before () const {return prot_info_ptr != NULL;} | ||||||
|  |  | ||||||
|  private: |  private: | ||||||
|   char *sun_path; |   char *sun_path; | ||||||
|   char *peer_sun_path; |   char *peer_sun_path; | ||||||
| @@ -524,7 +532,9 @@ class fhandler_socket: public fhandler_base | |||||||
|   int dup (fhandler_base *child); |   int dup (fhandler_base *child); | ||||||
|  |  | ||||||
|   void set_close_on_exec (bool val); |   void set_close_on_exec (bool val); | ||||||
|  |   int fixup_before_fork_exec (DWORD); | ||||||
|   void fixup_after_fork (HANDLE); |   void fixup_after_fork (HANDLE); | ||||||
|  |   void fixup_after_exec (); | ||||||
|   char *get_proc_fd_name (char *buf); |   char *get_proc_fd_name (char *buf); | ||||||
|  |  | ||||||
|   select_record *select_read (select_stuff *); |   select_record *select_read (select_stuff *); | ||||||
|   | |||||||
| @@ -151,6 +151,7 @@ fhandler_socket::fhandler_socket () : | |||||||
|   wsock_events (NULL), |   wsock_events (NULL), | ||||||
|   wsock_mtx (NULL), |   wsock_mtx (NULL), | ||||||
|   wsock_evt (NULL), |   wsock_evt (NULL), | ||||||
|  |   prot_info_ptr (NULL), | ||||||
|   sun_path (NULL), |   sun_path (NULL), | ||||||
|   peer_sun_path (NULL), |   peer_sun_path (NULL), | ||||||
|   status () |   status () | ||||||
| @@ -160,6 +161,8 @@ fhandler_socket::fhandler_socket () : | |||||||
|  |  | ||||||
| fhandler_socket::~fhandler_socket () | fhandler_socket::~fhandler_socket () | ||||||
| { | { | ||||||
|  |   if (prot_info_ptr) | ||||||
|  |     cfree (prot_info_ptr); | ||||||
|   if (sun_path) |   if (sun_path) | ||||||
|     cfree (sun_path); |     cfree (sun_path); | ||||||
|   if (peer_sun_path) |   if (peer_sun_path) | ||||||
| @@ -631,12 +634,62 @@ fhandler_socket::release_events () | |||||||
|   NtClose (wsock_mtx); |   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 | void | ||||||
| fhandler_socket::fixup_after_fork (HANDLE parent) | fhandler_socket::fixup_after_fork (HANDLE parent) | ||||||
| { | { | ||||||
|   fork_fixup (parent, wsock_mtx, "wsock_mtx"); |   fork_fixup (parent, wsock_mtx, "wsock_mtx"); | ||||||
|   fork_fixup (parent, wsock_evt, "wsock_evt"); |   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 | int | ||||||
| @@ -679,13 +732,33 @@ fhandler_socket::dup (fhandler_base *child) | |||||||
| 	} | 	} | ||||||
|     } |     } | ||||||
|   fhs->connect_state (connect_state ()); |   fhs->connect_state (connect_state ()); | ||||||
|   int ret = fhandler_base::dup (child); |  | ||||||
|   if (ret) |   if (!need_fixup_before ()) | ||||||
|     { |     { | ||||||
|       NtClose (fhs->wsock_evt); |       int ret = fhandler_base::dup (child); | ||||||
|       NtClose (fhs->wsock_mtx); |       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 | int __stdcall | ||||||
|   | |||||||
| @@ -302,6 +302,13 @@ frok::parent (volatile char * volatile stack_here) | |||||||
|   else |   else | ||||||
|     c_flags |= DETACHED_PROCESS; |     c_flags |= DETACHED_PROCESS; | ||||||
|  |  | ||||||
|  |   /* Some file types (currently only sockets) need extra effort in the | ||||||
|  |      parent after CreateProcess and before copying the datastructures | ||||||
|  |      to the child. So we have to start the child in suspend state, | ||||||
|  |      unfortunately, to avoid a race condition. */ | ||||||
|  |   if (cygheap->fdtab.need_fixup_before ()) | ||||||
|  |     c_flags |= CREATE_SUSPENDED; | ||||||
|  |  | ||||||
|   /* Remember if we need to load dynamically linked dlls. |   /* Remember if we need to load dynamically linked dlls. | ||||||
|      We do this here so that this information will be available |      We do this here so that this information will be available | ||||||
|      in the parent and, when the stack is copied, in the child. */ |      in the parent and, when the stack is copied, in the child. */ | ||||||
| @@ -369,6 +376,12 @@ frok::parent (volatile char * volatile stack_here) | |||||||
| 	  goto cleanup; | 	  goto cleanup; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  |       if (cygheap->fdtab.need_fixup_before ()) | ||||||
|  | 	{ | ||||||
|  | 	  cygheap->fdtab.fixup_before_fork (pi.dwProcessId); | ||||||
|  | 	  ResumeThread (pi.hThread); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|       CloseHandle (pi.hThread); |       CloseHandle (pi.hThread); | ||||||
|  |  | ||||||
|       /* Protect the handle but name it similarly to the way it will |       /* Protect the handle but name it similarly to the way it will | ||||||
|   | |||||||
| @@ -495,6 +495,34 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc) | |||||||
|   fd->uninterruptible_io (true); |   fd->uninterruptible_io (true); | ||||||
|   debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc); |   debug_printf ("fd %d, name '%s', soc %p", (int) fd, dev->name, soc); | ||||||
|  |  | ||||||
|  |   /* Usually sockets are inheritable IFS objects.  Unfortunately some virus | ||||||
|  |      scanners or other network-oriented software replace normal sockets | ||||||
|  |      with their own kind, which is running through a filter driver. | ||||||
|  |       | ||||||
|  |      The result is that these new sockets are not normal kernel objects | ||||||
|  |      anymore.  They are typically not marked as inheritable, nor are they | ||||||
|  |      IFS handles, as normal OS sockets are.  They are in fact not inheritable | ||||||
|  |      to child processes, and subsequent socket calls in the child process | ||||||
|  |      will fail with error 10038, WSAENOTSOCK.  And worse, while DuplicateHandle | ||||||
|  |      on these sockets mostly works in the process which created the socket, | ||||||
|  |      DuplicateHandle does quite often not work anymore in a child process. | ||||||
|  |      It does not help to mark them inheritable via SetHandleInformation. | ||||||
|  |  | ||||||
|  |      The only way to make these sockets usable in child processes is to | ||||||
|  |      duplicate them via WSADuplicateSocket/WSASocket calls.  This requires | ||||||
|  |      some incredible amount of extra processing so we only do this on | ||||||
|  |      affected systems.  If we recognize a non-inheritable socket, or if | ||||||
|  |      the XP1_IFS_HANDLES flag is not set in a call to WSADuplicateSocket, | ||||||
|  |      we switch to inheritance/dup via WSADuplicateSocket/WSASocket for | ||||||
|  |      that socket. */ | ||||||
|  |   DWORD flags; | ||||||
|  |   WSAPROTOCOL_INFOW wpi; | ||||||
|  |   if (!GetHandleInformation ((HANDLE) soc, &flags) | ||||||
|  |       || !(flags & HANDLE_FLAG_INHERIT) | ||||||
|  |       || WSADuplicateSocketW (soc, GetCurrentProcessId (), &wpi) | ||||||
|  |       || !(wpi.dwServiceFlags1 & XP1_IFS_HANDLES)) | ||||||
|  |     ((fhandler_socket *) fd)->init_fixup_before (); | ||||||
|  |  | ||||||
|   /* Raise default buffer sizes (instead of WinSock default 8K). |   /* Raise default buffer sizes (instead of WinSock default 8K). | ||||||
|  |  | ||||||
|      64K appear to have the best size/performance ratio for a default |      64K appear to have the best size/performance ratio for a default | ||||||
|   | |||||||
| @@ -529,7 +529,8 @@ spawn_guts (const char *prog_arg, const char *const *argv, | |||||||
|      and before copying the datastructures to the child.  So we have to start |      and before copying the datastructures to the child.  So we have to start | ||||||
|      the child in suspend state, unfortunately, to avoid a race condition. */ |      the child in suspend state, unfortunately, to avoid a race condition. */ | ||||||
|   if (!newargv.win16_exe |   if (!newargv.win16_exe | ||||||
|       && (!ch.iscygwin () || mode != _P_OVERLAY)) |       && (!ch.iscygwin () || mode != _P_OVERLAY | ||||||
|  | 	  || cygheap->fdtab.need_fixup_before ())) | ||||||
|     c_flags |= CREATE_SUSPENDED; |     c_flags |= CREATE_SUSPENDED; | ||||||
|  |  | ||||||
|   /* When ruid != euid we create the new process under the current original |   /* When ruid != euid we create the new process under the current original | ||||||
| @@ -656,6 +657,11 @@ loop: | |||||||
|   if (!(c_flags & CREATE_SUSPENDED)) |   if (!(c_flags & CREATE_SUSPENDED)) | ||||||
|     strace.write_childpid (ch, pi.dwProcessId); |     strace.write_childpid (ch, pi.dwProcessId); | ||||||
|  |  | ||||||
|  |   /* Fixup the parent data structures if needed and resume the child's | ||||||
|  |      main thread. */ | ||||||
|  |   if (cygheap->fdtab.need_fixup_before ()) | ||||||
|  |     cygheap->fdtab.fixup_before_exec (pi.dwProcessId); | ||||||
|  |  | ||||||
|   if (mode != _P_OVERLAY) |   if (mode != _P_OVERLAY) | ||||||
|     cygpid = cygwin_pid (pi.dwProcessId); |     cygpid = cygwin_pid (pi.dwProcessId); | ||||||
|   else |   else | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user