* 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.
This commit is contained in:
Christopher Faylor 2006-03-13 21:10:14 +00:00
parent 063fd12660
commit 84d3817405
11 changed files with 121 additions and 59 deletions

View File

@ -1,3 +1,29 @@
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

View 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;

View 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

View 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}}}
};

View File

@ -293,7 +293,6 @@ inside_kernel (CONTEXT *cx)
{
int res;
MEMORY_BASIC_INFORMATION m;
extern bool in_dllentry;
if (in_dllentry)
return true;

View 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);
/* 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);
}
if (!rc)
{
this_errno = geterrno_from_win_error ();
error = "CreateProcessA failed";
memset (&pi, 0, sizeof (pi));
goto cleanup;
}
strace.write_childpid (ch, pi.dwProcessId);
/* 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);
/* 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)");

View 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,

View 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;

View 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;
}

View 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)
{

View 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;