mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-31 11:30:56 +08:00
* 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:
parent
063fd12660
commit
84d3817405
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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}}}
|
||||
};
|
||||
|
||||
|
@ -293,7 +293,6 @@ inside_kernel (CONTEXT *cx)
|
||||
{
|
||||
int res;
|
||||
MEMORY_BASIC_INFORMATION m;
|
||||
extern bool in_dllentry;
|
||||
|
||||
if (in_dllentry)
|
||||
return true;
|
||||
|
@ -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)");
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user