diff options
author | Christopher Faylor <me@cgf.cx> | 2006-03-13 21:10:14 +0000 |
---|---|---|
committer | Christopher Faylor <me@cgf.cx> | 2006-03-13 21:10:14 +0000 |
commit | 84d38174056e438860213eb0cda919df89c06bd2 (patch) | |
tree | 061d434bdf553f8de3ea11667fdeeea29d7390a7 /winsup/cygwin/fork.cc | |
parent | 063fd1266048237629929240f923065bf9941abb (diff) | |
download | cygnal-84d38174056e438860213eb0cda919df89c06bd2.tar.gz cygnal-84d38174056e438860213eb0cda919df89c06bd2.tar.bz2 cygnal-84d38174056e438860213eb0cda919df89c06bd2.zip |
* 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.
Diffstat (limited to 'winsup/cygwin/fork.cc')
-rw-r--r-- | winsup/cygwin/fork.cc | 83 |
1 files changed, 49 insertions, 34 deletions
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)"); |