* dll_init.c (dll_list::load_after_fork): Don't clear in_forkee here.

* fork.cc (frok::errmsg): Rename from 'error'.
(frok::error): New function.  Handle conditional printing of error messages.
(frok::parent): Record hchild handle for use by error function.  Use
throughout.  Use error function rather than setting error pointer directly.
(fork): Clear is_forkee here.  Accommodate rename of 'error' to 'errmsg'.
* sigproc.cc (child_info::proc_retry): Detect EXITCODE_FORK_FAILED.
This commit is contained in:
Christopher Faylor 2011-05-28 20:09:04 +00:00
parent beaedec545
commit 8551087823
4 changed files with 70 additions and 46 deletions

View File

@ -1,3 +1,17 @@
2011-05-28 Christopher Faylor <me.cygwin2011@cgf.cx>
Ryan Johnson <ryan.johnson@cs.utoronto.ca>
* dll_init.c (dll_list::load_after_fork): Don't clear in_forkee here.
* fork.cc (frok::errmsg): Rename from 'error'.
(frok::error): New function. Handle conditional printing of error
messages.
(frok::parent): Record hchild handle for use by error function. Use
throughout. Use error function rather than setting error pointer
directly.
(fork): Clear is_forkee here. Accommodate rename of 'error' to
'errmsg'.
* sigproc.cc (child_info::proc_retry): Detect EXITCODE_FORK_FAILED.
2011-05-28 Christopher Faylor <me.cygwin2011@cgf.cx>
* fhandler.cc (handler_base_overlapped::wait_overlapped): Rework to

View File

@ -387,7 +387,6 @@ dll_list::load_after_fork (HANDLE parent)
preferred_block = reserve_at (d->name, (DWORD) h);
}
in_forkee = false;
}
struct dllcrt0_info

View File

@ -37,11 +37,13 @@ class frok
{
bool load_dlls;
child_info_fork ch;
const char *error;
const char *errmsg;
int child_pid;
int this_errno;
HANDLE hchild;
int __stdcall parent (volatile char * volatile here);
int __stdcall child (volatile char * volatile here);
bool error (const char *fmt, ...);
friend int fork ();
};
@ -163,6 +165,27 @@ sync_with_parent (const char *s, bool hang_self)
}
}
bool
frok::error (const char *fmt, ...)
{
DWORD exit_code = ch.exit_code;
if (!exit_code && hchild)
{
exit_code = ch.proc_retry (hchild);
if (!exit_code)
return false;
}
if (exit_code != EXITCODE_FORK_FAILED)
{
va_list ap;
static char buf[NT_MAX_PATH + 256];
va_start (ap, fmt);
__small_vsprintf (buf, fmt, ap);
errmsg = buf;
}
return true;
}
int __stdcall
frok::child (volatile char * volatile here)
{
@ -282,15 +305,16 @@ frok::parent (volatile char * volatile stack_here)
HANDLE forker_finished;
DWORD rc;
child_pid = -1;
error = NULL;
this_errno = 0;
bool fix_impersonation = false;
pinfo child;
static char errbuf[NT_MAX_PATH + 256];
int c_flags = GetPriorityClass (GetCurrentProcess ());
debug_printf ("priority class %d", c_flags);
errmsg = NULL;
hchild = NULL;
/* If we don't have a console, then don't create a console for the
child either. */
HANDLE console_handle = CreateFile ("CONOUT$", GENERIC_WRITE,
@ -319,7 +343,7 @@ frok::parent (volatile char * volatile stack_here)
if (forker_finished == NULL)
{
this_errno = geterrno_from_win_error ();
error = "unable to allocate forker_finished event";
error ("unable to allocate forker_finished event");
return -1;
}
@ -376,6 +400,7 @@ frok::parent (volatile char * volatile stack_here)
while (1)
{
hchild = NULL;
rc = CreateProcessW (myself->progname, /* image to run */
myself->progname, /* what we send in arg0 */
&sec_none_nih,
@ -390,8 +415,7 @@ frok::parent (volatile char * volatile stack_here)
if (!rc)
{
this_errno = geterrno_from_win_error ();
__small_sprintf (errbuf, "CreateProcessW failed for '%W'", myself->progname);
error = errbuf;
error ("CreateProcessW failed for '%W'", myself->progname);
memset (&pi, 0, sizeof (pi));
goto cleanup;
}
@ -403,24 +427,21 @@ frok::parent (volatile char * volatile stack_here)
}
CloseHandle (pi.hThread);
hchild = pi.hProcess;
/* Protect the handle but name it similarly to the way it will
be called in subproc handling. */
ProtectHandle1 (pi.hProcess, childhProc);
ProtectHandle1 (hchild, childhProc);
strace.write_childpid (ch, pi.dwProcessId);
/* Wait for subproc to initialize itself. */
if (!ch.sync (pi.dwProcessId, pi.hProcess, FORK_WAIT_TIMEOUT))
if (!ch.sync (pi.dwProcessId, hchild, FORK_WAIT_TIMEOUT))
{
DWORD exit_code = ch.proc_retry (pi.hProcess);
if (!exit_code)
if (!error ("forked process died unexpectedly, retry %d, exit code %d",
ch.retry, ch.exit_code))
continue;
this_errno = EAGAIN;
/* Not thread safe, but do we care? */
__small_sprintf (errbuf, "died waiting for longjmp before initialization, "
"retry %d, exit code %p", ch.retry, exit_code);
error = errbuf;
goto cleanup;
}
break;
@ -436,11 +457,7 @@ frok::parent (volatile char * volatile stack_here)
if (!child)
{
this_errno = get_errno () == ENOMEM ? ENOMEM : EAGAIN;
#ifdef DEBUGGING
error = "pinfo failed";
#else
syscall_printf ("pinfo failed");
#endif
goto cleanup;
}
@ -453,7 +470,7 @@ frok::parent (volatile char * volatile stack_here)
/* Fill in fields in the child's process table entry. */
child->dwProcessId = pi.dwProcessId;
child.hProcess = pi.hProcess;
child.hProcess = hchild;
/* Hopefully, this will succeed. The alternative to doing things this
way is to reserve space prior to calling CreateProcess and then fill
@ -462,16 +479,16 @@ frok::parent (volatile char * volatile stack_here)
we can't actually record the pid in the internal table. */
if (!child.remember (false))
{
TerminateProcess (pi.hProcess, 1);
TerminateProcess (hchild, 1);
this_errno = EAGAIN;
#ifdef DEBUGGING0
error = "child.remember failed";
error ("child remember failed");
#endif
goto cleanup;
}
#ifndef NO_SLOW_PID_REUSE
slow_pid_reuse (pi.hProcess);
slow_pid_reuse (hchild);
#endif
/* CHILD IS STOPPED */
@ -494,7 +511,7 @@ frok::parent (volatile char * volatile stack_here)
impure_beg = _impure_ptr;
impure_end = _impure_ptr + 1;
}
rc = child_copy (pi.hProcess, true,
rc = child_copy (hchild, true,
"stack", stack_here, ch.stackbottom,
impure, impure_beg, impure_end,
NULL);
@ -505,11 +522,7 @@ frok::parent (volatile char * volatile stack_here)
if (!rc)
{
this_errno = get_errno ();
DWORD exit_code;
if (!GetExitCodeProcess (pi.hProcess, &exit_code))
exit_code = 0xdeadbeef;
__small_sprintf (errbuf, "pid %u, exitval %p", pi.dwProcessId, exit_code);
error = errbuf;
error ("pid %u, exitval %p", pi.dwProcessId, ch.exit_code);
goto cleanup;
}
@ -517,29 +530,23 @@ frok::parent (volatile char * volatile stack_here)
for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
{
debug_printf ("copying data/bss of a linked dll");
if (!child_copy (pi.hProcess, true,
if (!child_copy (hchild, true,
"linked dll data", d->p.data_start, d->p.data_end,
"linked dll bss", d->p.bss_start, d->p.bss_end,
NULL))
{
this_errno = get_errno ();
#ifdef DEBUGGING
DWORD exit_code;
if (!GetExitCodeProcess (pi.hProcess, &exit_code))
exit_code = 0xdeadbeef;
__small_sprintf (errbuf, "pid %u, exitval %p", pi.dwProcessId, exit_code);
error = errbuf;
#endif
error ("couldn't copy linked dll data/bss");
goto cleanup;
}
}
/* Start thread, and then wait for it to reload dlls. */
resume_child (forker_finished);
if (!ch.sync (child->pid, pi.hProcess, FORK_WAIT_TIMEOUT))
if (!ch.sync (child->pid, hchild, FORK_WAIT_TIMEOUT))
{
this_errno = EAGAIN;
error = "died waiting for dll loading";
error ("died waiting for dll loading");
goto cleanup;
}
@ -553,14 +560,14 @@ frok::parent (volatile char * volatile stack_here)
for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
{
debug_printf ("copying data/bss for a loaded dll");
if (!child_copy (pi.hProcess, true,
if (!child_copy (hchild, true,
"loaded dll data", d->p.data_start, d->p.data_end,
"loaded dll bss", d->p.bss_start, d->p.bss_end,
NULL))
{
this_errno = get_errno ();
#ifdef DEBUGGING
error = "copying data/bss for a loaded dll";
error ("copying data/bss for a loaded dll");
#endif
goto cleanup;
}
@ -582,8 +589,8 @@ cleanup:
__malloc_unlock ();
/* Remember to de-allocate the fd table. */
if (pi.hProcess && !child.hProcess)
ForceCloseHandle1 (pi.hProcess, childhProc);
if (hchild && !child.hProcess)
ForceCloseHandle1 (hchild, childhProc);
if (forker_finished)
ForceCloseHandle (forker_finished);
debug_printf ("returning -1");
@ -637,6 +644,7 @@ fork ()
else
{
res = grouped.child (esp);
in_forkee = false;
ischild = true; /* might have been reset by fork mem copy */
}
}
@ -649,13 +657,13 @@ fork ()
}
else if (res < 0)
{
if (!grouped.error)
if (!grouped.errmsg)
syscall_printf ("fork failed - child pid %d, errno %d", grouped.child_pid, grouped.this_errno);
else
{
char buf[strlen (grouped.error) + sizeof ("child %d - , errno 4294967295 ")];
char buf[strlen (grouped.errmsg) + sizeof ("child %d - , errno 4294967295 ")];
strcpy (buf, "child %d - ");
strcat (buf, grouped.error);
strcat (buf, grouped.errmsg);
strcat (buf, ", errno %d");
system_printf (buf, grouped.child_pid, grouped.this_errno);
}

View File

@ -912,6 +912,9 @@ child_info::proc_retry (HANDLE h)
if (retry-- > 0)
exit_code = 0;
break;
case EXITCODE_FORK_FAILED: /* windows prevented us from forking */
break;
/* Count down non-recognized exit codes more quickly since they aren't
due to known conditions. */
default: