Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2006-03-14 00:10:14 +0300
committerChristopher Faylor <me@cgf.cx>2006-03-14 00:10:14 +0300
commit84d38174056e438860213eb0cda919df89c06bd2 (patch)
tree061d434bdf553f8de3ea11667fdeeea29d7390a7
parent063fd1266048237629929240f923065bf9941abb (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog26
-rw-r--r--winsup/cygwin/child_info.h4
-rw-r--r--winsup/cygwin/dcrt0.cc11
-rw-r--r--winsup/cygwin/environ.cc10
-rw-r--r--winsup/cygwin/exceptions.cc1
-rw-r--r--winsup/cygwin/fork.cc83
-rw-r--r--winsup/cygwin/heap.cc3
-rw-r--r--winsup/cygwin/pinfo.h5
-rw-r--r--winsup/cygwin/sigproc.cc19
-rw-r--r--winsup/cygwin/spawn.cc2
-rw-r--r--winsup/cygwin/winsup.h16
11 files changed, 121 insertions, 59 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index b99e6d9fe..ac979fcdb 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/child_info.h b/winsup/cygwin/child_info.h
index 9e6433dd5..03e8af58f 100644
--- a/winsup/cygwin/child_info.h
+++ b/winsup/cygwin/child_info.h
@@ -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;
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 149d37794..892a46581 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -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
diff --git a/winsup/cygwin/environ.cc b/winsup/cygwin/environ.cc
index eb99d2b51..23d0993a7 100644
--- a/winsup/cygwin/environ.cc
+++ b/winsup/cygwin/environ.cc
@@ -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}}}
};
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 587001e7a..60c1d1783 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -293,7 +293,6 @@ inside_kernel (CONTEXT *cx)
{
int res;
MEMORY_BASIC_INFORMATION m;
- extern bool in_dllentry;
if (in_dllentry)
return true;
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index eba4337a1..d31fd61a5 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -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)");
diff --git a/winsup/cygwin/heap.cc b/winsup/cygwin/heap.cc
index b45019981..bdf7a757f 100644
--- a/winsup/cygwin/heap.cc
+++ b/winsup/cygwin/heap.cc
@@ -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,
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 047fdae5b..93a862688 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -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;
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index c8f11324a..8f49320fa 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -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;
}
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index 668fb46ea..cac02d988 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -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)
{
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index eaae8e0ab..b8cdd15b7 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -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;