* 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>
|
2006-03-13 Christopher Faylor <cgf@timesys.com>
|
||||||
|
|
||||||
* dcrt0.cc (dll_crt0_0): Reorganize so that sigproc_init is called a
|
* 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 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
|
/* NOTE: Do not make gratuitous changes to the names or organization of the
|
||||||
below class. The layout is checksummed to determine compatibility between
|
below class. The layout is checksummed to determine compatibility between
|
||||||
@ -68,8 +68,10 @@ public:
|
|||||||
jmp_buf jmp; // where child will jump to
|
jmp_buf jmp; // where child will jump to
|
||||||
void *stacktop; // location of top of parent stack
|
void *stacktop; // location of top of parent stack
|
||||||
void *stackbottom; // location of bottom of parent stack
|
void *stackbottom; // location of bottom of parent stack
|
||||||
|
int retry; // number of times we've tried to fork
|
||||||
child_info_fork ();
|
child_info_fork ();
|
||||||
void handle_fork ();
|
void handle_fork ();
|
||||||
|
bool handle_failure (DWORD);
|
||||||
};
|
};
|
||||||
|
|
||||||
class fhandler_base;
|
class fhandler_base;
|
||||||
|
@ -122,6 +122,7 @@ extern "C"
|
|||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
int pinger;
|
int pinger;
|
||||||
#endif
|
#endif
|
||||||
|
int NO_COPY __api_fatal_exit_val = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
char *old_title;
|
char *old_title;
|
||||||
@ -640,6 +641,14 @@ get_cygwin_startup_info ()
|
|||||||
return res;
|
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_start &_data_start__
|
||||||
#define dll_data_end &_data_end__
|
#define dll_data_end &_data_end__
|
||||||
#define dll_bss_start &_bss_start__
|
#define dll_bss_start &_bss_start__
|
||||||
@ -1157,7 +1166,7 @@ __api_fatal (const char *fmt, ...)
|
|||||||
#ifdef DEBUGGING
|
#ifdef DEBUGGING
|
||||||
try_to_debug ();
|
try_to_debug ();
|
||||||
#endif
|
#endif
|
||||||
myself.exit (1);
|
myself.exit (__api_fatal_exit_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -39,6 +39,7 @@ static bool envcache = true;
|
|||||||
#ifdef USE_SERVER
|
#ifdef USE_SERVER
|
||||||
extern bool allow_server;
|
extern bool allow_server;
|
||||||
#endif
|
#endif
|
||||||
|
extern int fork_retry;
|
||||||
|
|
||||||
static char **lastenviron;
|
static char **lastenviron;
|
||||||
|
|
||||||
@ -515,7 +516,13 @@ subauth_id_init (const char *buf)
|
|||||||
static void
|
static void
|
||||||
set_chunksize (const char *buf)
|
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
|
static void
|
||||||
@ -587,6 +594,7 @@ static struct parse_thing
|
|||||||
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
|
{"tty", {NULL}, set_process_state, NULL, {{0}, {PID_USETTY}}},
|
||||||
{"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{false}, {true}}},
|
{"winsymlinks", {&allow_winsymlinks}, justset, NULL, {{false}, {true}}},
|
||||||
{"transparent_exe", {&transparent_exe}, 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}}}
|
{NULL, {0}, justset, 0, {{0}, {0}}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -293,7 +293,6 @@ inside_kernel (CONTEXT *cx)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
MEMORY_BASIC_INFORMATION m;
|
MEMORY_BASIC_INFORMATION m;
|
||||||
extern bool in_dllentry;
|
|
||||||
|
|
||||||
if (in_dllentry)
|
if (in_dllentry)
|
||||||
return true;
|
return true;
|
||||||
|
@ -33,6 +33,8 @@ details. */
|
|||||||
|
|
||||||
#define NPIDS_HELD 4
|
#define NPIDS_HELD 4
|
||||||
|
|
||||||
|
int fork_retry = 5;
|
||||||
|
|
||||||
/* Timeout to wait for child to start, parent to init child, etc. */
|
/* Timeout to wait for child to start, parent to init child, etc. */
|
||||||
/* FIXME: Once things stabilize, bump up to a few minutes. */
|
/* FIXME: Once things stabilize, bump up to a few minutes. */
|
||||||
#define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
|
#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)",
|
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)",
|
||||||
myself->progname, myself->progname, c_flags, &si, &pi);
|
myself->progname, myself->progname, c_flags, &si, &pi);
|
||||||
bool locked = __malloc_lock ();
|
bool locked = __malloc_lock ();
|
||||||
rc = CreateProcess (myself->progname, /* image to run */
|
time_t start_time;
|
||||||
myself->progname, /* what we send in arg0 */
|
ch.retry = fork_retry;
|
||||||
&sec_none_nih,
|
while (1)
|
||||||
&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 ();
|
start_time = time (NULL);
|
||||||
error = "CreateProcessA failed";
|
rc = CreateProcess (myself->progname, /* image to run */
|
||||||
memset (&pi, 0, sizeof (pi));
|
myself->progname, /* what we send in arg0 */
|
||||||
goto cleanup;
|
&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
|
if (!rc)
|
||||||
main thread. */
|
{
|
||||||
if (c_flags & CREATE_SUSPENDED)
|
this_errno = geterrno_from_win_error ();
|
||||||
{
|
error = "CreateProcessA failed";
|
||||||
cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
|
memset (&pi, 0, sizeof (pi));
|
||||||
ResumeThread (pi.hThread);
|
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_pid = cygwin_pid (pi.dwProcessId);
|
||||||
child.init (child_pid, 1, NULL);
|
child.init (child_pid, 1, NULL);
|
||||||
@ -330,7 +353,7 @@ frok::parent (void *stack_here)
|
|||||||
goto cleanup;
|
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;
|
child->nice = myself->nice;
|
||||||
|
|
||||||
/* Initialize things that are done later in dll_crt0_1 that aren't done
|
/* 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);
|
slow_pid_reuse (pi.hProcess);
|
||||||
#endif
|
#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 */
|
/* CHILD IS STOPPED */
|
||||||
debug_printf ("child is alive (but stopped)");
|
debug_printf ("child is alive (but stopped)");
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ details. */
|
|||||||
#include "cygheap.h"
|
#include "cygheap.h"
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
#include "cygwin_version.h"
|
#include "cygwin_version.h"
|
||||||
|
#include "child_info.h"
|
||||||
|
|
||||||
#define assert(x)
|
#define assert(x)
|
||||||
|
|
||||||
@ -75,7 +76,7 @@ heap_init ()
|
|||||||
if ((reserve_size -= page_const) < allocsize)
|
if ((reserve_size -= page_const) < allocsize)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!p)
|
if (!p && in_forkee && !fork_info->handle_failure (GetLastError ()))
|
||||||
api_fatal ("couldn't allocate heap, %E, base %p, top %p, "
|
api_fatal ("couldn't allocate heap, %E, base %p, top %p, "
|
||||||
"reserve_size %d, allocsize %d, page_const %d",
|
"reserve_size %d, allocsize %d, page_const %d",
|
||||||
cygheap->user_heap.base, cygheap->user_heap.top,
|
cygheap->user_heap.base, cygheap->user_heap.top,
|
||||||
|
@ -32,8 +32,9 @@ enum picom
|
|||||||
PICOM_PIPE_FHANDLER = 7
|
PICOM_PIPE_FHANDLER = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EXITCODE_SET 0x8000000
|
#define EXITCODE_SET 0x8000000
|
||||||
#define EXITCODE_NOSET 0x4000000
|
#define EXITCODE_NOSET 0x4000000
|
||||||
|
#define EXITCODE_RETRY 0x2000000
|
||||||
|
|
||||||
class fhandler_pipe;
|
class fhandler_pipe;
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ details. */
|
|||||||
#define WSSC 60000 // Wait for signal completion
|
#define WSSC 60000 // Wait for signal completion
|
||||||
#define WPSP 40000 // Wait for proc_subproc mutex
|
#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
|
#define NPROCS 256
|
||||||
|
|
||||||
@ -856,18 +856,23 @@ child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong)
|
|||||||
x -= WAIT_OBJECT_0;
|
x -= WAIT_OBJECT_0;
|
||||||
if (x >= n)
|
if (x >= n)
|
||||||
{
|
{
|
||||||
system_printf ("wait failed, pid %d, %E", pid);
|
system_printf ("wait failed, pid %u, %E", pid);
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (type == _PROC_EXEC && x == nsubproc_ready && myself->wr_proc_pipe)
|
if (x != nsubproc_ready)
|
||||||
|
res = type != _PROC_FORK;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
ForceCloseHandle1 (hProcess, childhProc);
|
if (type == _PROC_EXEC && myself->wr_proc_pipe)
|
||||||
hProcess = NULL;
|
{
|
||||||
|
ForceCloseHandle1 (hProcess, childhProc);
|
||||||
|
hProcess = NULL;
|
||||||
|
}
|
||||||
|
res = true;
|
||||||
}
|
}
|
||||||
sigproc_printf ("process %d synchronized, WFMO returned %d", pid, x);
|
sigproc_printf ("pid %u, WFMO returned %d, res %d", pid, x, res);
|
||||||
res = true;
|
|
||||||
}
|
}
|
||||||
return 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);
|
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)
|
switch (mode)
|
||||||
{
|
{
|
||||||
|
@ -35,10 +35,6 @@ details. */
|
|||||||
|
|
||||||
#define EXPORT_ALIAS(sym,symalias) extern "C" __typeof (sym) symalias __attribute__ ((alias(#sym)));
|
#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
|
#ifndef _WIN32_WINNT
|
||||||
#define _WIN32_WINNT 0x0501
|
#define _WIN32_WINNT 0x0501
|
||||||
#endif
|
#endif
|
||||||
@ -157,11 +153,9 @@ extern HANDLE tty_mutex;
|
|||||||
#define SIGTOMASK(sig) (1 << ((sig) - signal_shift_subtract))
|
#define SIGTOMASK(sig) (1 << ((sig) - signal_shift_subtract))
|
||||||
extern unsigned int signal_shift_subtract;
|
extern unsigned int signal_shift_subtract;
|
||||||
|
|
||||||
#ifdef NEW_MACRO_VARARGS
|
extern int __api_fatal_exit_val;
|
||||||
# define api_fatal(...) __api_fatal (__VA_ARGS__)
|
#define set_api_fatal_return(n) do {extern int __api_fatal_exit_val; __api_fatal_exit_val = (n);} while (0)
|
||||||
#else
|
#define api_fatal(fmt, args...) __api_fatal ("%P: *** " fmt,## args)
|
||||||
# define api_fatal(fmt, args...) __api_fatal ("%P: *** " fmt,## args)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#undef issep
|
#undef issep
|
||||||
#define issep(ch) (strchr (" \t\n\r", (ch)) != NULL)
|
#define issep(ch) (strchr (" \t\n\r", (ch)) != NULL)
|
||||||
@ -346,9 +340,11 @@ extern SYSTEM_INFO system_info;
|
|||||||
/* The title on program start. */
|
/* The title on program start. */
|
||||||
extern char *old_title;
|
extern char *old_title;
|
||||||
extern bool display_title;
|
extern bool display_title;
|
||||||
extern bool in_forkee;
|
|
||||||
extern bool transparent_exe;
|
extern bool transparent_exe;
|
||||||
|
|
||||||
|
extern bool in_forkee;
|
||||||
|
extern bool in_dllentry;
|
||||||
|
|
||||||
extern HANDLE hMainThread;
|
extern HANDLE hMainThread;
|
||||||
extern HANDLE hMainProc;
|
extern HANDLE hMainProc;
|
||||||
extern HANDLE hProcToken;
|
extern HANDLE hProcToken;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user