OSDN Git Service

* child_info.h (child_info_fork::handle_failure): Declare new function.
authorcgf <cgf>
Mon, 13 Mar 2006 21:10:14 +0000 (21:10 +0000)
committercgf <cgf>
Mon, 13 Mar 2006 21:10:14 +0000 (21:10 +0000)
(child_info_fork::retry): New field.
* dcrt0.cc (__api_fatal_exit_val): Define.
(child_info_fork::handle_failure): Define new function.
(__api_fatal): Exit using __api_fatal_exit_val value.
* environ.cc (set_fork_retry): Set fork_retry based on CYGWIN environment
variable.
(parse_thing): Add "fork_retry" setting.
* fork.cc (fork_retry): Define.
(frok::parent): Reorganize to allow retry of failed child creation if child
signalled that it was ok to do so.
* heap.cc (heap_init): Signal parent via handle_failure when VirtualAlloc
fails.
* pinfo.h (EXITCODE_RETRY): Declare.
* sigproc.cc (child_info::sync): Properly exit with failure condition if called
for fork and didn't see subproc_ready.
* spawn.cc (spawn_guts): Use windows pid as first argument.
* winsup.h: Remove obsolete NEW_MACRO_VARARGS define.
(__api_fatal_exit_val): Declare.
(set_api_fatal_return): Define.
(in_dllentry): Declare.
* exceptions.cc (inside_kernel): Remove unneeded in_dllentry declaration.

winsup/cygwin/ChangeLog
winsup/cygwin/child_info.h
winsup/cygwin/dcrt0.cc
winsup/cygwin/environ.cc
winsup/cygwin/exceptions.cc
winsup/cygwin/fork.cc
winsup/cygwin/heap.cc
winsup/cygwin/pinfo.h
winsup/cygwin/sigproc.cc
winsup/cygwin/spawn.cc
winsup/cygwin/winsup.h

index b99e6d9..ac979fc 100644 (file)
@@ -1,5 +1,31 @@
 2006-03-13  Christopher Faylor  <cgf@timesys.com>
 
+       * child_info.h (child_info_fork::handle_failure): Declare new function.
+       (child_info_fork::retry): New field.
+       * dcrt0.cc (__api_fatal_exit_val): Define.
+       (child_info_fork::handle_failure): Define new function.
+       (__api_fatal): Exit using __api_fatal_exit_val value.
+       * environ.cc (set_fork_retry): Set fork_retry based on CYGWIN
+       environment variable.
+       (parse_thing): Add "fork_retry" setting.
+       * fork.cc (fork_retry): Define.
+       (frok::parent): Reorganize to allow retry of failed child creation if
+       child signalled that it was ok to do so.
+       * heap.cc (heap_init): Signal parent via handle_failure when
+       VirtualAlloc fails.
+       * pinfo.h (EXITCODE_RETRY): Declare.
+       * sigproc.cc (child_info::sync): Properly exit with failure condition
+       if called for fork and didn't see subproc_ready.
+       * spawn.cc (spawn_guts): Use windows pid as first argument.
+       * winsup.h: Remove obsolete NEW_MACRO_VARARGS define.
+       (__api_fatal_exit_val): Declare.
+       (set_api_fatal_return): Define.
+       (in_dllentry): Declare.
+       * exceptions.cc (inside_kernel): Remove unneeded in_dllentry
+       declaration.
+
+2006-03-13  Christopher Faylor  <cgf@timesys.com>
+
        * dcrt0.cc (dll_crt0_0): Reorganize so that sigproc_init is called a
        little later.  Add a comment.
        * fork.cc (resume_child): Make void.
index 9e6433d..03e8af5 100644 (file)
@@ -29,7 +29,7 @@ enum child_info_types
 
 #define EXEC_MAGIC_SIZE sizeof(child_info)
 
-#define CURR_CHILD_INFO_MAGIC 0xc87757a7U
+#define CURR_CHILD_INFO_MAGIC 0x4160e87bU
 
 /* NOTE: Do not make gratuitous changes to the names or organization of the
    below class.  The layout is checksummed to determine compatibility between
@@ -68,8 +68,10 @@ public:
   jmp_buf jmp;         // where child will jump to
   void *stacktop;      // location of top of parent stack
   void *stackbottom;   // location of bottom of parent stack
+  int retry;           // number of times we've tried to fork
   child_info_fork ();
   void handle_fork ();
+  bool handle_failure (DWORD);
 };
 
 class fhandler_base;
index 149d377..892a465 100644 (file)
@@ -122,6 +122,7 @@ extern "C"
 #ifdef DEBUGGING
   int pinger;
 #endif
+  int NO_COPY __api_fatal_exit_val = 1;
 };
 
 char *old_title;
@@ -640,6 +641,14 @@ get_cygwin_startup_info ()
   return res;
 }
 
+bool
+child_info_fork::handle_failure (DWORD err)
+{
+  if (retry > 0)
+    ExitProcess (EXITCODE_RETRY);
+  return 0;
+}
+
 #define dll_data_start &_data_start__
 #define dll_data_end &_data_end__
 #define dll_bss_start &_bss_start__
@@ -1157,7 +1166,7 @@ __api_fatal (const char *fmt, ...)
 #ifdef DEBUGGING
   try_to_debug ();
 #endif
-  myself.exit (1);
+  myself.exit (__api_fatal_exit_val);
 }
 
 void
index eb99d2b..23d0993 100644 (file)
@@ -39,6 +39,7 @@ static bool envcache = true;
 #ifdef USE_SERVER
 extern bool allow_server;
 #endif
+extern int fork_retry;
 
 static char **lastenviron;
 
@@ -515,7 +516,13 @@ subauth_id_init (const char *buf)
 static void
 set_chunksize (const char *buf)
 {
-  wincap.set_chunksize (strtol (buf, NULL, 0));
+  wincap.set_chunksize (strtoul (buf, NULL, 0));
+}
+
+static void
+set_fork_retry (const char *buf)
+{
+  fork_retry = strtoul (buf, NULL, 0);
 }
 
 static void
@@ -587,6 +594,7 @@ static struct parse_thing
   {"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
   {"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{false}, {true}}},
   {"transparent_exe", {&transparent_exe}, justset, NULL, {{false}, {true}}},
+  {"fork_retry", {func: set_fork_retry}, isfunc, NULL, {{0}, {5}}},
   {NULL, {0}, justset, 0, {{0}, {0}}}
 };
 
index 587001e..60c1d17 100644 (file)
@@ -293,7 +293,6 @@ inside_kernel (CONTEXT *cx)
 {
   int res;
   MEMORY_BASIC_INFORMATION m;
-  extern bool in_dllentry;
 
   if (in_dllentry)
     return true;
index eba4337..d31fd61 100644 (file)
@@ -33,6 +33,8 @@ details. */
 
 #define NPIDS_HELD 4
 
+int fork_retry = 5;
+
 /* Timeout to wait for child to start, parent to init child, etc.  */
 /* FIXME: Once things stabilize, bump up to a few minutes.  */
 #define FORK_WAIT_TIMEOUT (300 * 1000)     /* 300 seconds */
@@ -287,34 +289,55 @@ frok::parent (void *stack_here)
   syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)",
                  myself->progname, myself->progname, c_flags, &si, &pi);
   bool locked = __malloc_lock ();
-  rc = CreateProcess (myself->progname, /* image to run */
-                     myself->progname, /* what we send in arg0 */
-                     &sec_none_nih,
-                     &sec_none_nih,
-                     TRUE,       /* inherit handles from parent */
-                     c_flags,
-                     NULL,       /* environment filled in later */
-                     0,          /* use current drive/directory */
-                     &si,
-                     &pi);
-
-  if (!rc)
+  time_t start_time;
+  ch.retry = fork_retry;
+  while (1)
     {
-      this_errno = geterrno_from_win_error ();
-      error = "CreateProcessA failed";
-      memset (&pi, 0, sizeof (pi));
-      goto cleanup;
-    }
+      start_time = time (NULL);
+      rc = CreateProcess (myself->progname, /* image to run */
+                         myself->progname, /* what we send in arg0 */
+                         &sec_none_nih,
+                         &sec_none_nih,
+                         TRUE,   /* inherit handles from parent */
+                         c_flags,
+                         NULL,   /* environment filled in later */
+                         0,      /* use current drive/directory */
+                         &si,
+                         &pi);
+
+      if (!rc)
+       {
+         this_errno = geterrno_from_win_error ();
+         error = "CreateProcessA failed";
+         memset (&pi, 0, sizeof (pi));
+         goto cleanup;
+       }
 
-  /* Fixup the parent datastructure if needed and resume the child's
-     main thread. */
-  if (c_flags & CREATE_SUSPENDED)
-    {
-      cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
-      ResumeThread (pi.hThread);
-    }
+      /* Fixup the parent datastructure if needed and resume the child's
+        main thread. */
+      if (c_flags & CREATE_SUSPENDED)
+       {
+         cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
+         ResumeThread (pi.hThread);
+       }
 
-  strace.write_childpid (ch, pi.dwProcessId);
+      strace.write_childpid (ch, pi.dwProcessId);
+
+      /* Wait for subproc to initialize itself. */
+      if (!ch.sync (pi.dwProcessId, pi.hProcess, FORK_WAIT_TIMEOUT))
+       {
+         DWORD exit_code;
+         if (GetExitCodeProcess (pi.hProcess, &exit_code) && exit_code == EXITCODE_RETRY)
+           {
+             ch.retry--;
+             continue;
+           }
+         this_errno = EAGAIN;
+         error = "died waiting for longjmp before initialization";
+         goto cleanup;
+       }
+      break;
+    }
 
   child_pid = cygwin_pid (pi.dwProcessId);
   child.init (child_pid, 1, NULL);
@@ -330,7 +353,7 @@ frok::parent (void *stack_here)
       goto cleanup;
     }
 
-  child->start_time = time (NULL); /* Register child's starting time. */
+  child->start_time = start_time; /* Register child's starting time. */
   child->nice = myself->nice;
 
   /* Initialize things that are done later in dll_crt0_1 that aren't done
@@ -369,14 +392,6 @@ frok::parent (void *stack_here)
   slow_pid_reuse (pi.hProcess);
 #endif
 
-  /* Wait for subproc to initialize itself. */
-  if (!ch.sync (child->pid, pi.hProcess, FORK_WAIT_TIMEOUT))
-    {
-      this_errno = EAGAIN;
-      error = "died waiting for longjmp before initialization";
-      goto cleanup;
-    }
-
   /* CHILD IS STOPPED */
   debug_printf ("child is alive (but stopped)");
 
index b450199..bdf7a75 100644 (file)
@@ -21,6 +21,7 @@ details. */
 #include "cygheap.h"
 #include "registry.h"
 #include "cygwin_version.h"
+#include "child_info.h"
 
 #define assert(x)
 
@@ -75,7 +76,7 @@ heap_init ()
          if ((reserve_size -= page_const) < allocsize)
            break;
        }
-      if (!p)
+      if (!p && in_forkee && !fork_info->handle_failure (GetLastError ()))
        api_fatal ("couldn't allocate heap, %E, base %p, top %p, "
                   "reserve_size %d, allocsize %d, page_const %d",
                   cygheap->user_heap.base, cygheap->user_heap.top,
index 047fdae..93a8626 100644 (file)
@@ -32,8 +32,9 @@ enum picom
   PICOM_PIPE_FHANDLER = 7
 };
 
-#define EXITCODE_SET 0x8000000
-#define EXITCODE_NOSET 0x4000000
+#define EXITCODE_SET   0x8000000
+#define EXITCODE_NOSET 0x4000000
+#define EXITCODE_RETRY 0x2000000
 
 class fhandler_pipe;
 
index c8f1132..8f49320 100644 (file)
@@ -39,7 +39,7 @@ details. */
 #define WSSC             60000 // Wait for signal completion
 #define WPSP             40000 // Wait for proc_subproc mutex
 
-#define no_signals_available(x) (!hwait_sig || ((x) && myself->exitcode & EXITCODE_SET) || &_my_tls == _sig_tls)
+#define no_signals_available(x) (!hwait_sig || ((x) && myself->exitcode & EXITCODE_SET) || &_my_tls == _sig_tls || in_dllentry)
 
 #define NPROCS 256
 
@@ -856,18 +856,23 @@ child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong)
   x -= WAIT_OBJECT_0;
   if (x >= n)
     {
-      system_printf ("wait failed, pid %d, %E", pid);
+      system_printf ("wait failed, pid %u, %E", pid);
       res = false;
     }
   else
     {
-      if (type == _PROC_EXEC && x == nsubproc_ready && myself->wr_proc_pipe)
+      if (x != nsubproc_ready)
+       res = type != _PROC_FORK;
+      else
        {
-         ForceCloseHandle1 (hProcess, childhProc);
-         hProcess = NULL;
+         if (type == _PROC_EXEC && myself->wr_proc_pipe)
+           {
+             ForceCloseHandle1 (hProcess, childhProc);
+             hProcess = NULL;
+           }
+         res = true;
        }
-      sigproc_printf ("process %d synchronized, WFMO returned %d", pid, x);
-      res = true;
+      sigproc_printf ("pid %u, WFMO returned %d, res %d", pid, x, res);
     }
   return res;
 }
index 668fb46..cac02d9 100644 (file)
@@ -846,7 +846,7 @@ spawn_guts (const char * prog_arg, const char *const *argv,
 
   sigproc_printf ("spawned windows pid %d", pi.dwProcessId);
 
-  synced = ch.sync (pid, pi.hProcess, INFINITE);
+  synced = ch.sync (pi.dwProcessId, pi.hProcess, INFINITE);
 
   switch (mode)
     {
index eaae8e0..b8cdd15 100644 (file)
@@ -35,10 +35,6 @@ details. */
 
 #define EXPORT_ALIAS(sym,symalias) extern "C" __typeof (sym) symalias __attribute__ ((alias(#sym)));
 
-#if !defined(__STDC_VERSION__) || __STDC_VERSION__ >= 199900L
-#define NEW_MACRO_VARARGS
-#endif
-
 #ifndef _WIN32_WINNT
 #define _WIN32_WINNT 0x0501
 #endif
@@ -157,11 +153,9 @@ extern HANDLE tty_mutex;
 #define SIGTOMASK(sig) (1 << ((sig) - signal_shift_subtract))
 extern unsigned int signal_shift_subtract;
 
-#ifdef NEW_MACRO_VARARGS
-# define api_fatal(...) __api_fatal (__VA_ARGS__)
-#else
-# define api_fatal(fmt, args...) __api_fatal ("%P: *** " fmt,## args)
-#endif
+extern int __api_fatal_exit_val;
+#define set_api_fatal_return(n) do {extern int __api_fatal_exit_val; __api_fatal_exit_val = (n);} while (0)
+#define api_fatal(fmt, args...) __api_fatal ("%P: *** " fmt,## args)
 
 #undef issep
 #define issep(ch) (strchr (" \t\n\r", (ch)) != NULL)
@@ -346,9 +340,11 @@ extern SYSTEM_INFO system_info;
 /* The title on program start. */
 extern char *old_title;
 extern bool display_title;
-extern bool in_forkee;
 extern bool transparent_exe;
 
+extern bool in_forkee;
+extern bool in_dllentry;
+
 extern HANDLE hMainThread;
 extern HANDLE hMainProc;
 extern HANDLE hProcToken;