OSDN Git Service

* dtable.cc (dtable::release): Check for socket. Change
authorcorinna <corinna>
Thu, 26 Oct 2000 10:13:41 +0000 (10:13 +0000)
committercorinna <corinna>
Thu, 26 Oct 2000 10:13:41 +0000 (10:13 +0000)
        cnt_need_fixup_before accordingly.
        (dtable::dup2): Ditto.
        (dtable::fixup_before_fork): New method.
        (dtable::fixup_before_exec): Ditto.
        * dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add
        definition for methods `dec_need_fixup_before', `inc_need_fixup_before',
        `need_fixup_before', `fixup_before_exec' and `fixup_before_fork'.
        * fhandler.h (class fhandler_base): Slight rearrangements. Add
        definitions for methods `fixup_before_fork_exec'.
        (class fhandler_socket): Eliminate superfluous constructor.
        Add member `prot_info_ptr'. Add destructor. Add definitions for
        methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and
        `fixup_after_exec'.
        * fork.cc (fork_parent): Care for file types which need a fixup
        before fork. Start child in suspended state then.
        * net.cc: New global variable `ws2_32_handle' and `wsadata'.
        (fdsock): Check for Winsock version. Call `set_socket_inheritance'
        only if Winsock version < 2.0. Care for `need_fixup' count in fdtab.
        (cygwin_socket): Eliminate call to `set_socket_inheritance'.
        (cygwin_accept): Ditto.
        (cygwin_rcmd): Ditto.
        (cygwin_rresvport): Ditto.
        (cygwin_rexec): Ditto.
        (socketpair): Ditto.
        (fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate
        space for the WSAPROTOCOL_INFOA struct used in fixup.
        (fhandler_socket::~fhandler_socket): New destructor.
        (fhandler_socket::fixup_before_fork_exec): New method.
        (fhandler_socket::fixup_after_fork): Ditto.
        (fhandler_socket::dup): Ditto.
        (wsock_init): New static function.
        (LoadDLLinitfunc (wsock32)): Rearranged.
        (LoadDLLinitfunc (ws2_32)): New function.
        (dummy_autoload): Add autoload statemants for `WSADuplicateSocketA'
        and `WSASocketA'.
        * spawn.cc (spawn_guts): Care for file types which need a fixup
        before exec. Start child in suspended state then.

winsup/cygwin/ChangeLog
winsup/cygwin/dtable.cc
winsup/cygwin/dtable.h
winsup/cygwin/fhandler.h
winsup/cygwin/fork.cc
winsup/cygwin/net.cc
winsup/cygwin/spawn.cc

index 98a5b70..fbb75b3 100644 (file)
@@ -1,3 +1,44 @@
+Thu Oct 26 11:51:59 2000  Corinna Vinschen <corinna@vinschen.de>
+
+       * dtable.cc (dtable::release): Check for socket. Change
+       cnt_need_fixup_before accordingly.
+       (dtable::dup2): Ditto.
+       (dtable::fixup_before_fork): New method.
+       (dtable::fixup_before_exec): Ditto.
+       * dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add
+       definition for methods `dec_need_fixup_before', `inc_need_fixup_before',
+       `need_fixup_before', `fixup_before_exec' and `fixup_before_fork'.
+       * fhandler.h (class fhandler_base): Slight rearrangements. Add
+       definitions for methods `fixup_before_fork_exec'.
+       (class fhandler_socket): Eliminate superfluous constructor.
+       Add member `prot_info_ptr'. Add destructor. Add definitions for
+       methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and
+       `fixup_after_exec'.
+       * fork.cc (fork_parent): Care for file types which need a fixup
+       before fork. Start child in suspended state then.
+       * net.cc: New global variable `ws2_32_handle' and `wsadata'.
+       (fdsock): Check for Winsock version. Call `set_socket_inheritance'
+       only if Winsock version < 2.0. Care for `need_fixup' count in fdtab.
+       (cygwin_socket): Eliminate call to `set_socket_inheritance'.
+       (cygwin_accept): Ditto.
+       (cygwin_rcmd): Ditto.
+       (cygwin_rresvport): Ditto.
+       (cygwin_rexec): Ditto.
+       (socketpair): Ditto.
+       (fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate
+       space for the WSAPROTOCOL_INFOA struct used in fixup.
+       (fhandler_socket::~fhandler_socket): New destructor.
+       (fhandler_socket::fixup_before_fork_exec): New method.
+       (fhandler_socket::fixup_after_fork): Ditto.
+       (fhandler_socket::dup): Ditto.
+       (wsock_init): New static function.
+       (LoadDLLinitfunc (wsock32)): Rearranged.
+       (LoadDLLinitfunc (ws2_32)): New function.
+       (dummy_autoload): Add autoload statemants for `WSADuplicateSocketA'
+       and `WSASocketA'.
+       * spawn.cc (spawn_guts): Care for file types which need a fixup
+       before exec. Start child in suspended state then.
+
 Wed Oct 25 20:49:59 2000  Christopher Faylor <cgf@cygnus.com>
 
        * signal.cc (kill_pgrp): Don't limit sending of signals to stopped
index b08d547..4df5699 100644 (file)
@@ -153,6 +153,8 @@ dtable::release (int fd)
 {
   if (!not_open (fd))
     {
+      if ((fds[fd]->get_device () & FH_DEVMASK) == FH_SOCKET)
+        dec_need_fixup_before ();
       delete fds[fd];
       fds[fd] = NULL;
     }
@@ -377,6 +379,11 @@ dtable::dup2 (int oldfd, int newfd)
   if (!not_open (newfd))
     _close (newfd);
   fds[newfd] = newfh;
+
+  /* Count sockets. */
+  if ((fds[newfd]->get_device () & FH_DEVMASK) == FH_SOCKET)
+    inc_need_fixup_before ();
+
   ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
   MALLOC_CHECK;
 
@@ -444,6 +451,34 @@ dtable::select_except (int fd, select_record *s)
 /* Function to walk the fd table after an exec and perform
    per-fhandler type fixups. */
 void
+dtable::fixup_before_fork (DWORD target_proc_id)
+{
+  SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
+  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);
+      }
+  ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
+}
+
+void
+dtable::fixup_before_exec (DWORD target_proc_id)
+{
+  SetResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
+  fhandler_base *fh;
+  for (size_t i = 0; i < size; i++)
+    if ((fh = fds[i]) != NULL && (!fh->get_close_on_exec ()))
+      {
+       debug_printf ("fd %d(%s)", i, fh->get_name ());
+       fh->fixup_before_fork_exec (target_proc_id);
+      }
+  ReleaseResourceLock(LOCK_FD_LIST,WRITE_LOCK|READ_LOCK,"dup");
+}
+
+void
 dtable::fixup_after_exec (HANDLE parent, size_t sz, fhandler_base **f)
 {
   size = sz;
index 1952e94..3851dbf 100644 (file)
@@ -16,13 +16,26 @@ class dtable
   fhandler_base **fds;
   fhandler_base **fds_on_hold;
   int first_fd_for_open;
+  int cnt_need_fixup_before;
 public:
   size_t size;
-  dtable () {first_fd_for_open = 3;}
+
+  dtable ()
+    : first_fd_for_open(3), cnt_need_fixup_before(0) {}
+
+  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; }
+
   int vfork_child_dup ();
   void vfork_parent_restore ();
   fhandler_base *dup_worker (fhandler_base *oldfh);
   int extend (int howmuch);
+  void fixup_before_exec (DWORD win_proc_id);
+  void fixup_before_fork (DWORD win_proc_id);
   void fixup_after_fork (HANDLE);
   fhandler_base *build_fhandler (int fd, DWORD dev, const char *name,
                                 int unit = -1);
index 43b33ed..f8c3bd7 100644 (file)
@@ -197,7 +197,10 @@ public:
   void set_need_fork_fixup () { FHSETF (FFIXUP); }
 
   virtual void set_close_on_exec (int val);
-  virtual void fixup_after_fork (HANDLE parent);
+
+  virtual void fixup_before_fork_exec (DWORD) {}
+  virtual void fixup_after_fork (HANDLE);
+  virtual void fixup_after_exec (HANDLE) {}
 
   int get_symlink_p () { return FHISSETF (SYMLINK); }
   void set_symlink_p (int val) { FHCONDSETF (val, SYMLINK); }
@@ -291,8 +294,6 @@ public:
   virtual int raw_read (void *ptr, size_t ulen);
   virtual int raw_write (const void *ptr, size_t ulen);
 
-  virtual void fixup_after_exec (HANDLE) {}
-
   /* Virtual accessor functions to hide the fact
      that some fd's have two handles. */
   virtual HANDLE get_handle () const { return io_handle; }
@@ -320,9 +321,11 @@ class fhandler_socket: public fhandler_base
 {
 private:
   int addr_family;
+  struct _WSAPROTOCOL_INFOA *prot_info_ptr;
+
 public:
   fhandler_socket (const char *name = 0);
-  fhandler_socket (unsigned int, const char *name = 0);
+  ~fhandler_socket ();
   int get_socket () const { return (int) get_handle(); }
   fhandler_socket * is_socket () { return this; }
   int write (const void *ptr, size_t len);
@@ -332,6 +335,11 @@ public:
   off_t lseek (off_t, int) { return 0; }
   int close ();
   void hclose (HANDLE) {close ();}
+  int dup (fhandler_base *child);
+
+  virtual void fixup_before_fork_exec (DWORD);
+  void fixup_after_fork (HANDLE);
+  void fixup_after_exec (HANDLE parent) { fixup_after_fork (parent); }
 
   select_record *select_read (select_record *s);
   select_record *select_write (select_record *s);
index c304d34..87315a4 100644 (file)
@@ -341,6 +341,13 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
   else
     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 (fdtab.need_fixup_before ())
+    c_flags |= CREATE_SUSPENDED;
+
   hParent = NULL;
   if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
                        DUPLICATE_SAME_ACCESS))
@@ -429,6 +436,14 @@ fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls
       return -1;
     }
 
+  /* Fixup the parent datastructure if needed and resume the child's
+     main thread. */
+  if (fdtab.need_fixup_before ())
+    {
+      fdtab.fixup_before_fork (pi.dwProcessId);
+      ResumeThread (pi.hThread);
+    }
+
   pinfo forked (cygwin_pid (pi.dwProcessId), 1);
 
   /* Initialize things that are done later in dll_crt0_1 that aren't done
index d5e358c..7f587a1 100644 (file)
@@ -22,7 +22,8 @@ details. */
 #include <netdb.h>
 #include <fcntl.h>
 #include "autoload.h"
-#include <winsock.h>
+#include <winsock2.h>
+#include "cygheap.h"
 #include "cygerrno.h"
 #include "fhandler.h"
 #include "path.h"
@@ -43,6 +44,9 @@ int __stdcall rresvport (int *);
 int sscanf (const char *, const char *, ...);
 } /* End of "C" section */
 
+extern HANDLE ws2_32_handle;
+WSADATA wsadata;
+
 /* Cygwin internal */
 static SOCKET __stdcall
 set_socket_inheritance (SOCKET sock)
@@ -308,9 +312,12 @@ cygwin_getprotobynumber (int number)
 fhandler_socket *
 fdsock (int fd, const char *name, SOCKET soc)
 {
+  if (wsadata.wVersion < 512) /* < Winsock 2.0 */
+    soc = set_socket_inheritance (soc);
   fhandler_socket *fh = (fhandler_socket *) fdtab.build_fhandler (fd, FH_SOCKET, name);
   fh->set_io_handle ((HANDLE) soc);
   fh->set_flags (O_RDWR);
+  fdtab.inc_need_fixup_before ();
   return fh;
 }
 
@@ -339,8 +346,6 @@ cygwin_socket (int af, int type, int protocol)
          goto done;
        }
 
-      soc = set_socket_inheritance (soc);
-
       const char *name;
       if (af == AF_INET)
        name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp");
@@ -720,8 +725,6 @@ cygwin_accept (int fd, struct sockaddr *peer, int *len)
        set_winsock_errno ();
       else
        {
-         res = set_socket_inheritance (res);
-
          fdsock (res_fd, sock->get_name (), res);
          res = res_fd;
        }
@@ -1593,15 +1596,11 @@ cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
     goto done;
   else
     {
-      res = set_socket_inheritance (res);
-
       fdsock (res_fd, "/dev/tcp", res);
       res = res_fd;
     }
   if (fd2p)
     {
-      fd2s = set_socket_inheritance (fd2s);
-
       fdsock (*fd2p, "/dev/tcp", fd2s);
     }
 done:
@@ -1625,8 +1624,6 @@ cygwin_rresvport (int *port)
     goto done;
   else
     {
-      res = set_socket_inheritance (res);
-
       fdsock (res_fd, "/dev/tcp", res);
       res = res_fd;
     }
@@ -1658,8 +1655,6 @@ cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
     goto done;
   else
     {
-      res = set_socket_inheritance (res);
-
       fdsock (res_fd, "/dev/tcp", res);
       res = res_fd;
     }
@@ -1766,11 +1761,8 @@ socketpair (int, int type, int, int *sb)
   closesocket (newsock);
   res = 0;
 
-  insock = set_socket_inheritance (insock);
-
   fdsock (sb[0], "/dev/tcp", insock);
 
-  outsock = set_socket_inheritance (outsock);
   fdsock (sb[1], "/dev/tcp", outsock);
 
 done:
@@ -1779,6 +1771,18 @@ done:
   return res;
 }
 
+/* sethostent: standards? */
+extern "C" void
+sethostent (int)
+{
+}
+
+/* endhostent: standards? */
+extern "C" void
+endhostent (void)
+{
+}
+
 /**********************************************************************/
 /* fhandler_socket */
 
@@ -1786,18 +1790,80 @@ fhandler_socket::fhandler_socket (const char *name) :
        fhandler_base (FH_SOCKET, name)
 {
   set_cb (sizeof *this);
+  set_need_fork_fixup ();
+  prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
+                                                sizeof (WSAPROTOCOL_INFOA));
 }
 
-/* sethostent: standards? */
-extern "C" void
-sethostent (int)
+fhandler_socket::~fhandler_socket ()
 {
+  if (prot_info_ptr)
+    cfree (prot_info_ptr);
 }
 
-/* endhostent: standards? */
-extern "C" void
-endhostent (void)
+void
+fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id)
 {
+  int ret = 1;
+
+  if (prot_info_ptr &&
+      (ret = WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr)))
+    {
+      debug_printf ("WSADuplicateSocket error");
+      set_winsock_errno ();
+    }
+  if (!ret && ws2_32_handle)
+    {
+      debug_printf ("WSADuplicateSocket went fine, dwServiceFlags1=%d",
+                   prot_info_ptr->dwServiceFlags1);
+    }
+  else
+    {
+      fhandler_base::fixup_before_fork_exec (win_proc_id);
+      debug_printf ("Without Winsock 2.0");
+    }
+}
+
+void
+fhandler_socket::fixup_after_fork (HANDLE parent)
+{
+  SOCKET new_sock = INVALID_SOCKET;
+
+  debug_printf ("WSASocket begin, dwServiceFlags1=%d",
+               prot_info_ptr->dwServiceFlags1);
+  if (prot_info_ptr &&
+      (new_sock = WSASocketA (FROM_PROTOCOL_INFO,
+                              FROM_PROTOCOL_INFO,
+                              FROM_PROTOCOL_INFO,
+                              prot_info_ptr, 0, 0)) == INVALID_SOCKET)
+    {
+      debug_printf ("WSASocket error");
+      set_winsock_errno ();
+    }
+  if (new_sock != INVALID_SOCKET && ws2_32_handle)
+    {
+      debug_printf ("WSASocket went fine");
+      set_io_handle ((HANDLE) new_sock);
+    }
+  else
+    {
+      fhandler_base::fixup_after_fork (parent);
+      debug_printf ("Without Winsock 2.0");
+    }
+}
+
+int
+fhandler_socket::dup (fhandler_base *child)
+{
+  fhandler_socket *fhs = (fhandler_socket *) child;
+  fhs->set_io_handle (get_io_handle ());
+  fhs->fixup_before_fork_exec (GetCurrentProcessId ());
+  if (ws2_32_handle)
+    {
+      fhs->fixup_after_fork (hMainProc);
+      return 0;
+    }
+  return fhandler_base::dup (child);
 }
 
 int
@@ -2011,12 +2077,28 @@ fhandler_socket::fcntl (int cmd, void *arg)
   return res;
 }
 
+static void
+wsock_init ()
+{
+  int res = WSAStartup ((2<<8) | 2, &wsadata);
+
+  debug_printf ("res %d", res);
+  debug_printf ("wVersion %d", wsadata.wVersion);
+  debug_printf ("wHighVersion %d", wsadata.wHighVersion);
+  debug_printf ("szDescription %s", wsadata.szDescription);
+  debug_printf ("szSystemStatus %s", wsadata.szSystemStatus);
+  debug_printf ("iMaxSockets %d", wsadata.iMaxSockets);
+  debug_printf ("iMaxUdpDg %d", wsadata.iMaxUdpDg);
+  debug_printf ("lpVendorInfo %d", wsadata.lpVendorInfo);
+
+  if (FIONBIO  != REAL_FIONBIO)
+    debug_printf ("****************  FIONBIO  != REAL_FIONBIO");
+}
+
 extern "C" {
 /* Initialize WinSock */
 LoadDLLinitfunc (wsock32)
 {
-  WSADATA p;
-  int res;
   HANDLE h;
 
   if ((h = LoadLibrary ("wsock32.dll")) != NULL)
@@ -2026,29 +2108,32 @@ LoadDLLinitfunc (wsock32)
   else
     return 0;          /* Already done by another thread? */
 
-  res = WSAStartup ((2<<8) | 2, &p);
+  if (!ws2_32_handle)
+    wsock_init ();
 
-  debug_printf ("res %d", res);
-  debug_printf ("wVersion %d", p.wVersion);
-  debug_printf ("wHighVersion %d", p.wHighVersion);
-  debug_printf ("szDescription %s", p.szDescription);
-  debug_printf ("szSystemStatus %s", p.szSystemStatus);
-  debug_printf ("iMaxSockets %d", p.iMaxSockets);
-  debug_printf ("iMaxUdpDg %d", p.iMaxUdpDg);
-  debug_printf ("lpVendorInfo %d", p.lpVendorInfo);
+  return 0;
+}
 
-  if (FIONBIO  != REAL_FIONBIO)
-    debug_printf ("****************  FIONBIO  != REAL_FIONBIO");
+/* Initialize WinSock2.0 */
+LoadDLLinitfunc (ws2_32)
+{
+  HANDLE h;
+
+  if ((h = LoadLibrary ("ws2_32.dll")) == NULL)
+    return 0;          /* Already done or not available. */
+  ws2_32_handle = h;
+
+  if (!wsock32_handle)
+    wsock_init ();
 
   return 0;
 }
 
-LoadDLLinit (wsock32)
-
 static void dummy_autoload (void) __attribute__ ((unused));
 static void
 dummy_autoload (void)
 {
+LoadDLLinit (wsock32)
 LoadDLLfunc (WSAAsyncSelect, 16, wsock32)
 LoadDLLfunc (WSACleanup, 0, wsock32)
 LoadDLLfunc (WSAGetLastError, 0, wsock32)
@@ -2084,5 +2169,9 @@ LoadDLLfunc (sendto, 24, wsock32)
 LoadDLLfunc (setsockopt, 20, wsock32)
 LoadDLLfunc (shutdown, 8, wsock32)
 LoadDLLfunc (socket, 12, wsock32)
+
+LoadDLLinit (ws2_32)
+LoadDLLfuncEx (WSADuplicateSocketA, 12, ws2_32, 1)
+LoadDLLfuncEx (WSASocketA, 24, ws2_32, 1)
 }
 }
index 2e0490d..35aac93 100644 (file)
@@ -540,6 +540,14 @@ skip_arg_parsing:
   if (mode != _P_OVERLAY)
     flags |= CREATE_SUSPENDED;
 
+  /* 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 (fdtab.need_fixup_before ())
+    flags |= CREATE_SUSPENDED;
+
+
   /* Build windows style environment list */
   char *envblock;
   if (real_path.iscygexec ())
@@ -656,6 +664,15 @@ skip_arg_parsing:
       return -1;
     }
 
+  /* Fixup the parent datastructure if needed and resume the child's
+     main thread. */
+  if (fdtab.need_fixup_before ())
+    {
+      fdtab.fixup_before_exec (pi.dwProcessId);
+      if (mode == _P_OVERLAY)
+        ResumeThread (pi.hThread);
+    }
+
   if (mode == _P_OVERLAY)
     cygpid = myself->pid;
   else