* 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:
parent
9edadc960e
commit
280fdd0b67
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue