* 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:
parent
beaedec545
commit
8551087823
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue