* dcrt0.cc (getstack): New function.

(alloc_stack): Use tls stuff for stack info rather than calling VirtualQuery.
(dll_crt0_0): Initialize _impure_ptr stuff much earlier.  Move
init_console_handler here.
* fork.cc (class frok): New class renamed from local fork() struct.
(stack_base): Change argument type.  Use tls stuff to determine stack info
rather than calling VirtualQuery.
(frok::child): Rename from fork_child.  Eliminate now unneeded arguments.
(frok::parent): Rename from fork_parent and ditto.  Set error and errno as
appropriate.  Fixup impersonation in cleanup, if needed.  Try harder to set
errno appropriately.
(fork): Define "grouped" as a frok type.  Deal with errors from fork_parent
here.
* init.cc (dll_entry): Remove init_console_handler call.
This commit is contained in:
Christopher Faylor 2005-09-28 15:18:49 +00:00
parent 9edadc960e
commit 280fdd0b67
4 changed files with 131 additions and 64 deletions

View File

@ -1,3 +1,22 @@
2005-09-28 Christopher Faylor <cgf@timesys.com>
* dcrt0.cc (getstack): New function.
(alloc_stack): Use tls stuff for stack info rather than calling
VirtualQuery.
(dll_crt0_0): Initialize _impure_ptr stuff much earlier. Move
init_console_handler here.
* fork.cc (class frok): New class renamed from local fork() struct.
(stack_base): Change argument type. Use tls stuff to determine stack
info rather than calling VirtualQuery.
(frok::child): Rename from fork_child. Eliminate now unneeded
arguments.
(frok::parent): Rename from fork_parent and ditto. Set error and errno
as appropriate. Fixup impersonation in cleanup, if needed. Try harder
to set errno appropriately.
(fork): Define "grouped" as a frok type. Deal with errors from
fork_parent here.
* init.cc (dll_entry): Remove init_console_handler call.
2005-09-28 Christopher Faylor <cgf@timesys.com>
* pinfo.cc (_pinfo::dup_proc_pipe): Ignore error if the child process

View File

@ -502,22 +502,29 @@ alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
b[0] = '\0';
}
void *getstack (void *) __attribute__ ((noinline));
volatile char *
getstack (volatile char *p)
{
*p |= 0;
return p - 4096;
}
/* extend the stack prior to fork longjmp */
static void
alloc_stack (child_info_fork *ci)
{
/* FIXME: adding 16384 seems to avoid a stack copy problem during
fork on Win95, but I don't know exactly why yet. DJ */
volatile char b[ci->stacksize + 16384];
if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
api_fatal ("fork: couldn't get stack info, %E");
if (sm.AllocationBase == ci->stacktop)
ci->stacksize = 0;
volatile char *esp;
__asm__ volatile ("movl %%esp,%0": "=r" (esp));
if (_tlsbase != ci->stackbottom)
alloc_stack_hard_way (ci, esp);
else
alloc_stack_hard_way (ci, b + sizeof (b) - 1);
{
while (_tlstop > ci->stacktop)
esp = getstack (esp);
ci->stacksize = 0;
}
}
#ifdef DEBUGGING
@ -629,6 +636,12 @@ get_cygwin_startup_info ()
void __stdcall
dll_crt0_0 ()
{
init_console_handler (TRUE);
_impure_ptr = _GLOBAL_REENT;
_impure_ptr->_stdin = &_impure_ptr->__sf[0];
_impure_ptr->_stdout = &_impure_ptr->__sf[1];
_impure_ptr->_stderr = &_impure_ptr->__sf[2];
_impure_ptr->_current_locale = "C";
wincap.init ();
initial_env ();
@ -931,11 +944,6 @@ _dll_crt0 ()
*main_environ = NULL;
char padding[CYGTLS_PADSIZE];
_impure_ptr = _GLOBAL_REENT;
_impure_ptr->_stdin = &_impure_ptr->__sf[0];
_impure_ptr->_stdout = &_impure_ptr->__sf[1];
_impure_ptr->_stderr = &_impure_ptr->__sf[2];
_impure_ptr->_current_locale = "C";
if (child_proc_info && child_proc_info->type == _PROC_FORK)
user_data->forkee = true;

View File

@ -42,20 +42,28 @@ details. */
#define dll_bss_start &_bss_start__
#define dll_bss_end &_bss_end__
static void
stack_base (child_info_fork &ch)
class frok
{
MEMORY_BASIC_INFORMATION m;
memset (&m, 0, sizeof m);
if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
system_printf ("couldn't get memory info, %E");
dll *first_dll;
bool load_dlls;
child_info_fork ch;
const char *error;
int child_pid;
int this_errno;
int __stdcall parent (void *esp);
int __stdcall child (void *esp);
friend int fork ();
};
ch.stacktop = m.AllocationBase;
ch.stackbottom = (LPBYTE) m.BaseAddress + m.RegionSize;
ch.stacksize = (DWORD) ch.stackbottom - (DWORD) &m;
static void
stack_base (child_info_fork *ch)
{
ch->stackbottom = _tlsbase;
ch->stacktop = &ch;
ch->stacksize = (char *) ch->stackbottom - (char *) &ch;
debug_printf ("bottom %p, top %p, stack %p, size %d, reserve %d",
ch.stackbottom, ch.stacktop, &m, ch.stacksize,
(DWORD) ch.stackbottom - (DWORD) ch.stacktop);
ch->stackbottom, ch->stacktop, &ch, ch->stacksize,
(char *) ch->stackbottom - (char *) ch->stacktop);
}
/* Copy memory from parent to child.
@ -153,9 +161,10 @@ sync_with_parent (const char *s, bool hang_self)
}
}
static int __stdcall
fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
int __stdcall
frok::child (void *)
{
HANDLE& hParent = ch.parent;
extern void fixup_hooks_after_fork ();
extern void fixup_timers_after_fork ();
debug_printf ("child is running. pid %d, ppid %d, stack here %p",
@ -247,6 +256,7 @@ fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
return 0;
}
#define NO_SLOW_PID_REUSE
#ifndef NO_SLOW_PID_REUSE
static void
slow_pid_reuse (HANDLE h)
@ -274,12 +284,17 @@ slow_pid_reuse (HANDLE h)
}
#endif
static int __stdcall
fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_info_fork &ch)
int __stdcall
frok::parent (void *stack_here)
{
HANDLE forker_finished;
DWORD rc;
PROCESS_INFORMATION pi = {0, NULL, 0, 0};
child_pid = -1;
error = NULL;
this_errno = 0;
bool fix_impersonation = false;
pinfo child;
pthread::atforkprepare ();
@ -318,7 +333,8 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
if (forker_finished == NULL)
{
system_printf ("unable to allocate forker_finished event, %E");
this_errno = geterrno_from_win_error ();
error = "child %d - unable to allocate forker_finished event, %E";
return -1;
}
@ -326,7 +342,7 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
ch.forker_finished = forker_finished;
stack_base (ch);
stack_base (&ch);
si.cb = sizeof (STARTUPINFO);
si.lpReserved2 = (LPBYTE) &ch;
@ -334,6 +350,7 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
/* Remove impersonation */
cygheap->user.deimpersonate ();
fix_impersonation = true;
syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)",
myself->progname, myself->progname, c_flags, &si, &pi);
@ -351,15 +368,12 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
if (!rc)
{
__seterrno ();
syscall_printf ("CreateProcessA failed, %E");
ForceCloseHandle (forker_finished);
/* Restore impersonation */
cygheap->user.reimpersonate ();
__malloc_unlock ();
return -1;
this_errno = geterrno_from_win_error ();
error = "child %d - CreateProcessA failed, %E";
goto cleanup;
}
/* Fixup the parent datastructure if needed and resume the child's
main thread. */
if (cygheap->fdtab.need_fixup_before ())
@ -368,14 +382,17 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
ResumeThread (pi.hThread);
}
int child_pid = cygwin_pid (pi.dwProcessId);
pinfo child (child_pid, 1);
child_pid = cygwin_pid (pi.dwProcessId);
child.init (child_pid, 1, NULL);
if (!child)
{
this_errno = get_errno () == ENOMEM ? ENOMEM : EAGAIN;
#ifdef DEBUGGING
error = "child %d - pinfo failed";
#else
syscall_printf ("pinfo failed");
if (get_errno () != ENOMEM)
set_errno (EAGAIN);
#endif
goto cleanup;
}
@ -388,6 +405,7 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
/* Restore impersonation */
cygheap->user.reimpersonate ();
fix_impersonation = false;
ProtectHandle (pi.hThread);
/* Protect the handle but name it similarly to the way it will
@ -406,7 +424,10 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
if (!child.remember (false))
{
TerminateProcess (pi.hProcess, 1);
set_errno (EAGAIN);
this_errno = EAGAIN;
#ifdef DEBUGGING
error = "child %d - child.remember failed";
#endif
goto cleanup;
}
@ -417,8 +438,8 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
/* Wait for subproc to initialize itself. */
if (!ch.sync (child->pid, pi.hProcess, FORK_WAIT_TIMEOUT))
{
if (NOTSTATE (child, PID_EXITED))
system_printf ("child %d died waiting for longjmp before initialization", child_pid);
this_errno = EAGAIN;
error = "child %d - died waiting for longjmp before initialization";
goto cleanup;
}
@ -461,7 +482,13 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,
d->p.bss_start, d->p.bss_end,
NULL))
goto cleanup;
{
this_errno = get_errno ();
#ifdef DEBUGGING
error = "child %d - fork_copy for linked dll data/bss failed";
#endif
goto cleanup;
}
}
/* Start thread, and wait for it to reload dlls. */
@ -469,8 +496,8 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
goto cleanup;
else if (!ch.sync (child->pid, pi.hProcess, FORK_WAIT_TIMEOUT))
{
if (NOTSTATE (child, PID_EXITED))
system_printf ("child %d died waiting for dll loading", child_pid);
this_errno = EAGAIN;
error = "child %d died waiting for dll loading";
goto cleanup;
}
@ -487,7 +514,13 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,
d->p.bss_start, d->p.bss_end,
NULL))
goto cleanup;
{
this_errno = get_errno ();
#ifdef DEBUGGING
error = "child %d - copying data/bss for a loaded dll";
#endif
goto cleanup;
}
}
/* Start the child up again. */
resume_child (forker_finished);
@ -502,7 +535,9 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
return child_pid;
/* Common cleanup code for failure cases */
cleanup:
cleanup:
if (fix_impersonation)
cygheap->user.reimpersonate ();
if (locked)
__malloc_unlock ();
@ -513,19 +548,14 @@ fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_
ForceCloseHandle (pi.hThread);
if (forker_finished)
ForceCloseHandle (forker_finished);
debug_printf ("returning -1");
return -1;
}
extern "C" int
fork ()
{
struct
{
dll *first_dll;
bool load_dlls;
child_info_fork ch;
} grouped;
frok grouped;
MALLOC_CHECK;
debug_printf ("entering");
@ -546,15 +576,26 @@ fork ()
}
sig_send (NULL, __SIGHOLD);
int res = setjmp (grouped.ch.jmp);
if (res)
res = fork_child (grouped.ch.parent, grouped.first_dll, grouped.load_dlls);
int res;
int ischild = setjmp (grouped.ch.jmp);
if (!ischild)
res = grouped.parent (esp);
else
res = fork_parent (grouped.ch.parent, grouped.first_dll, grouped.load_dlls, esp, grouped.ch);
sig_send (NULL, __SIGNOHOLD);
res = grouped.child (esp);
MALLOC_CHECK;
if (ischild || res > 0)
/* everything is ok */;
else
{
if (!grouped.error)
syscall_printf ("fork failed - child pid %d", grouped.child_pid);
else
system_printf (grouped.error, grouped.child_pid);
set_errno (grouped.this_errno);
}
syscall_printf ("%d = fork()", res);
sig_send (NULL, __SIGNOHOLD);
return res;
}
#ifdef DEBUGGING

View File

@ -148,7 +148,6 @@ dll_entry (HANDLE h, DWORD reason, void *static_load)
case DLL_PROCESS_ATTACH:
cygwin_hmodule = (HMODULE) h;
dynamically_loaded = (static_load == NULL);
init_console_handler (TRUE);
/* Is the stack at an unusual address? This is, an address which
is in the usual space occupied by the process image, but below