OSDN Git Service

* winsup.h (child_copy): Change prototype to match new functionality.
authorcgf <cgf>
Sat, 17 Dec 2005 04:36:38 +0000 (04:36 +0000)
committercgf <cgf>
Sat, 17 Dec 2005 04:36:38 +0000 (04:36 +0000)
* cygheap.cc (cygheap_fixup_in_child): Accommodate new child_copy arguments.
* dcrt0.cc (dll_data_start): Move definition here from fork.
(dll_data_end): Ditto.
(dll_bss_start): Ditto.
(dll_bss_end): Ditto.
(handle_fork): New function.  Called when forked to deal with fork issues and
copy data to this process from the parent.
(dll_crt0_0): Call handle_fork when _PROC_FORK condition.
(dll_crt0): Don't copy user_data when we've forked.  Don't zero first element
of main_environment ever.
(cygwin_dll_init): Ditto.
* fork.cc (child_copy): Rename from fork_copy and change arguments so that each
pair of things to copy gets its own descriptor.
(frok::child): Remove fixup_mmaps_after_fork call here.  Move to handle_fork in
dcrt0.cc.
(frok::parent): Use child_copy rather than fork_copy and accommodate changes in
parameters.
* exceptions.cc (setup_handler): Delay test of whether we're locked until after
GetThreadContext has been called since there are apparently cases where
SuspendThread does not cause an immediate thread suspension.

winsup/cygwin/ChangeLog
winsup/cygwin/cygheap.cc
winsup/cygwin/dcrt0.cc
winsup/cygwin/exceptions.cc
winsup/cygwin/fork.cc
winsup/cygwin/winsup.h

index 3ae7043..e2c2c77 100644 (file)
@@ -1,5 +1,32 @@
 2005-12-16  Christopher Faylor  <cgf@timesys.com>
 
+       * winsup.h (child_copy): Change prototype to match new functionality.
+       * cygheap.cc (cygheap_fixup_in_child): Accommodate new child_copy
+       arguments.
+       * dcrt0.cc (dll_data_start): Move definition here from fork.
+       (dll_data_end): Ditto.
+       (dll_bss_start): Ditto.
+       (dll_bss_end): Ditto.
+       (handle_fork): New function.  Called when forked to deal with fork
+       issues and copy data to this process from the parent.
+       (dll_crt0_0): Call handle_fork when _PROC_FORK condition.
+       (dll_crt0): Don't copy user_data when we've forked.  Don't zero first
+       element of main_environment ever.
+       (cygwin_dll_init): Ditto.
+       * fork.cc (child_copy): Rename from fork_copy and change arguments so
+       that each pair of things to copy gets its own descriptor.
+       (frok::child): Remove fixup_mmaps_after_fork call here.  Move to
+       handle_fork in dcrt0.cc.
+       (frok::parent): Use child_copy rather than fork_copy and accommodate
+       changes in parameters.
+
+       * exceptions.cc (setup_handler): Delay test of whether we're locked
+       until after GetThreadContext has been called since there are apparently
+       cases where SuspendThread does not cause an immediate thread
+       suspension.
+
+2005-12-16  Christopher Faylor  <cgf@timesys.com>
+
        * init.cc (dll_entry): Call prime_threads after dll_crt0_0 to avoid
        conflicts between heap allocation and thread stack allocation.
 
index cf64684..122e620 100644 (file)
@@ -59,7 +59,7 @@ cygheap_fixup_in_child (bool execed)
   cygheap_max = child_proc_info->cygheap;
   cygheap = (init_cygheap *) cygheap_max;
   _csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap);
-  child_copy (child_proc_info->parent, child_proc_info->dwProcessId, "cygheap", cygheap, cygheap_max);
+  child_copy (child_proc_info->parent, false, "cygheap", cygheap, cygheap_max, NULL);
   cygheap_init ();
   debug_fixup_after_fork_exec ();
 
index 8df5e6e..fcff2c3 100644 (file)
@@ -635,6 +635,35 @@ get_cygwin_startup_info ()
   return res;
 }
 
+#define dll_data_start &_data_start__
+#define dll_data_end &_data_end__
+#define dll_bss_start &_bss_start__
+#define dll_bss_end &_bss_end__
+
+void
+handle_fork ()
+{
+  alloc_stack (fork_info);
+  cygheap_fixup_in_child (false);
+  memory_init ();
+  set_myself (NULL);
+  HANDLE hp = fork_info->parent;
+  child_copy (hp, false,
+             "dll data", dll_data_start, dll_data_end,
+             "dll bss", dll_bss_start, dll_bss_end,
+             "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
+             NULL);
+  /* step 2 now that the dll has its heap filled in, we can fill in the
+     user's data and bss since user_data is now filled out. */
+  child_copy (hp, false,
+             "data", user_data->data_start, user_data->data_end,
+             "bss", user_data->bss_start, user_data->bss_end,
+             NULL);
+
+  if (fixup_mmaps_after_fork (hp))
+    api_fatal ("recreate_mmaps_after_fork_failed");
+}
+
 void __stdcall
 dll_crt0_0 ()
 {
@@ -675,10 +704,7 @@ dll_crt0_0 ()
       switch (child_proc_info->type)
        {
          case _PROC_FORK:
-           alloc_stack (fork_info);
-           cygheap_fixup_in_child (false);
-           memory_init ();
-           set_myself (NULL);
+           handle_fork ();
            break;
          case _PROC_SPAWN:
          case _PROC_EXEC:
@@ -937,7 +963,9 @@ _dll_crt0 ()
     system_printf ("internal error: couldn't determine location of thread function on stack.  Expect signal problems.");
 
   main_environ = user_data->envptr;
+#if 0
   *main_environ = NULL;
+#endif
 
   char padding[CYGTLS_PADSIZE];
 
@@ -954,7 +982,7 @@ void
 dll_crt0 (per_process *uptr)
 {
   /* Set the local copy of the pointer into the user space. */
-  if (uptr && uptr != user_data)
+  if (!user_data->forkee && uptr && uptr != user_data)
     {
       memcpy (user_data, uptr, per_process_overwrite);
       *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
@@ -989,7 +1017,9 @@ cygwin_dll_init ()
   user_data->fmode_ptr = &_fmode;
 
   main_environ = user_data->envptr;
+#if 0
   *main_environ = NULL;
+#endif
   initialize_main_tls((char *)&_my_tls);
   dll_crt0_1 (NULL);
 }
index 4844a02..9b989ee 100644 (file)
@@ -786,17 +786,12 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
          ResumeThread (hth);
          break;
        }
-      if (tls->incyg || tls->spinning || tls->locked ())
-       sigproc_printf ("incyg %d, spinning %d, locked %d\n",
-                       tls->incyg, tls->spinning, tls->locked ());
-      else
-       {
-         cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
-         if (!GetThreadContext (hth, &cx))
-           system_printf ("couldn't get context of main thread, %E");
-         else if (interruptible (cx.Eip))
-           interrupted = tls->interrupt_now (&cx, sig, handler, siga);
-       }
+      cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
+      if (!GetThreadContext (hth, &cx))
+       system_printf ("couldn't get context of main thread, %E");
+      else if (interruptible (cx.Eip) &&
+              !(tls->incyg || tls->spinning || tls->locked ()))
+       interrupted = tls->interrupt_now (&cx, sig, handler, siga);
 
       res = ResumeThread (hth);
       if (interrupted)
index 374eb0f..98ef427 100644 (file)
@@ -37,11 +37,6 @@ details. */
 /* FIXME: Once things stabilize, bump up to a few minutes.  */
 #define FORK_WAIT_TIMEOUT (300 * 1000)     /* 300 seconds */
 
-#define dll_data_start &_data_start__
-#define dll_data_end &_data_end__
-#define dll_bss_start &_bss_start__
-#define dll_bss_end &_bss_end__
-
 class frok
 {
   dll *first_dll;
@@ -55,60 +50,6 @@ class frok
   friend int fork ();
 };
 
-/* Copy memory from parent to child.
-   The result is a boolean indicating success.  */
-
-static int
-fork_copy (PROCESS_INFORMATION& pi, const char *what, ...)
-{
-  va_list args;
-  char *low;
-  int pass = 0;
-
-  va_start (args, what);
-
-  while ((low = va_arg (args, char *)))
-    {
-      char *high = va_arg (args, char *);
-      DWORD todo = wincap.chunksize () ?: high - low;
-      char *here;
-
-      for (here = low; here < high; here += todo)
-       {
-         DWORD done = 0;
-         if (here + todo > high)
-           todo = high - here;
-         int res;
-         if (pi.hThread)
-           res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
-         else
-           res = ReadProcessMemory (pi.hProcess, here, here, todo, &done);
-         debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
-                       low, high, res);
-         if (!res || todo != done)
-           {
-             if (!res)
-               __seterrno ();
-             /* If this happens then there is a bug in our fork
-                implementation somewhere. */
-             system_printf ("%s pass %d failed, %p..%p, done %d, windows pid %u, %E",
-                           what, pass, low, high, done, pi.dwProcessId);
-             goto err;
-           }
-       }
-
-      pass++;
-    }
-
-  debug_printf ("done");
-  return 1;
-
- err:
-  TerminateProcess (pi.hProcess, 1);
-  set_errno (EAGAIN);
-  return 0;
-}
-
 static int
 resume_child (HANDLE forker_finished)
 {
@@ -198,9 +139,6 @@ frok::child (void *)
 
   MALLOC_CHECK;
 
-  if (fixup_mmaps_after_fork (hParent))
-    api_fatal ("recreate_mmaps_after_fork_failed");
-
 #ifdef USE_SERVER
   /* Incredible but true:  If we use sockets and SYSV IPC shared memory,
      there's a good chance that a duplicated socket in the child occupies
@@ -367,7 +305,6 @@ frok::parent (void *stack_here)
       goto cleanup;
     }
 
-
   /* Fixup the parent datastructure if needed and resume the child's
      main thread. */
   if (cygheap->fdtab.need_fixup_before ())
@@ -446,22 +383,21 @@ frok::parent (void *stack_here)
 
 
   MALLOC_CHECK;
-  void *impure_beg;
-  void *impure_end;
+  const void *impure_beg;
+  const void *impure_end;
+  const char *impure;
   if (&_my_tls == _main_tls)
-    impure_beg = impure_end = NULL;
+    impure_beg = impure_end = impure = NULL;
   else
     {
+      impure = "impure";
       impure_beg = _impure_ptr;
       impure_end = _impure_ptr + 1;
     }
-  rc = fork_copy (pi, "user/cygwin data",
-                 user_data->data_start, user_data->data_end,
-                 user_data->bss_start, user_data->bss_end,
-                 cygheap->user_heap.base, cygheap->user_heap.ptr,
-                 stack_here, ch.stackbottom,
-                 dll_data_start, dll_data_end,
-                 dll_bss_start, dll_bss_end, impure_beg, impure_end, NULL);
+  rc = child_copy (pi.hProcess, true,
+                  "stack", stack_here, ch.stackbottom,
+                  impure, impure_beg, impure_end,
+                  NULL);
 
   __malloc_unlock ();
   locked = false;
@@ -473,9 +409,10 @@ frok::parent (void *stack_here)
   for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
     {
       debug_printf ("copying data/bss of a linked dll");
-      if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,
-                                                d->p.bss_start, d->p.bss_end,
-                                                NULL))
+      if (!child_copy (pi.hProcess, true,
+                      "linked dll data", d->p.data_start, d->p.data_end,
+                      "linked dll bss", d->p.bss_start, d->p.bss_end,
+                      NULL))
        {
          this_errno = get_errno ();
 #ifdef DEBUGGING
@@ -505,9 +442,10 @@ frok::parent (void *stack_here)
       for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
        {
          debug_printf ("copying data/bss for a loaded dll");
-         if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,
-                                                    d->p.bss_start, d->p.bss_end,
-                                                    NULL))
+         if (!child_copy (pi.hProcess, true,
+                          "loaded dll data", d->p.data_start, d->p.data_end,
+                          "loaded dll bss", d->p.bss_start, d->p.bss_end,
+                          NULL))
            {
              this_errno = get_errno ();
 #ifdef DEBUGGING
@@ -690,13 +628,52 @@ vfork ()
 #endif
 }
 
-int
-child_copy (HANDLE h, DWORD pid, const char *what, void *child_start, void *child_end)
+/* Copy memory from one process to another. */
+
+bool
+child_copy (HANDLE hp, bool write, ...)
 {
-  PROCESS_INFORMATION pi;
-  pi.hProcess = h;
-  pi.dwProcessId = pid;
-  pi.hThread = NULL;
-  debug_printf ("%s, start %p, end %p", what, child_start, child_end);
-  return fork_copy (pi, what, child_start, child_end, NULL);
+  va_list args;
+  va_start (args, write);
+  static const char *huh[] = {"read", "write"};
+
+  char *what;
+  while ((what = va_arg (args, char *)))
+    {
+      char *low = va_arg (args, char *);
+      char *high = va_arg (args, char *);
+      DWORD todo = wincap.chunksize () ?: high - low;
+      char *here;
+
+      for (here = low; here < high; here += todo)
+       {
+         DWORD done = 0;
+         if (here + todo > high)
+           todo = high - here;
+         int res;
+         if (write)
+           res = WriteProcessMemory (hp, here, here, todo, &done);
+         else
+           res = ReadProcessMemory (hp, here, here, todo, &done);
+         debug_printf ("hp %p, low %p, high %p, res %d", hp, low, high, res);
+         if (!res || todo != done)
+           {
+             if (!res)
+               __seterrno ();
+             /* If this happens then there is a bug in our fork
+                implementation somewhere. */
+             system_printf ("%s %s copy failed, %p..%p, done %d, windows pid %u, %E",
+                           what, huh[write], low, high, done);
+             goto err;
+           }
+       }
+    }
+
+  debug_printf ("done");
+  return true;
+
+ err:
+  TerminateProcess (hp, 1);
+  set_errno (EAGAIN);
+  return false;
 }
index d441877..72d5aab 100644 (file)
@@ -284,7 +284,7 @@ extern void multiple_cygwin_problem (const char *, unsigned, unsigned);
 
 extern "C" void vklog (int priority, const char *message, va_list ap);
 extern "C" void klog (int priority, const char *message, ...);
-int child_copy (HANDLE, DWORD, const char *, void *, void *);
+bool child_copy (HANDLE, bool, ...);
 
 int symlink_worker (const char *, const char *, bool, bool)
   __attribute__ ((regparm (3)));