Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2005-09-28 19:18:49 +0400
committerChristopher Faylor <me@cgf.cx>2005-09-28 19:18:49 +0400
commit280fdd0b67c3dbd3cee12bf6dbe363f222d98342 (patch)
tree483b37f8f41a0ce565559a2a5340f2fe5c3c9e57
parent9edadc960e8bd94cbfd812156fed35557309e2f5 (diff)
* 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.
-rw-r--r--winsup/cygwin/ChangeLog19
-rw-r--r--winsup/cygwin/dcrt0.cc38
-rw-r--r--winsup/cygwin/fork.cc137
-rw-r--r--winsup/cygwin/init.cc1
4 files changed, 131 insertions, 64 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 6df8c85d6..65d7a0fb9 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,24 @@
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
has just gone away.
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index ca8b601c9..953c93ec0 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -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;
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 92e27aa78..64fd53893 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -42,20 +42,28 @@ details. */
#define dll_bss_start &_bss_start__
#define dll_bss_end &_bss_end__
+class frok
+{
+ 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 ();
+};
+
static void
-stack_base (child_info_fork &ch)
+stack_base (child_info_fork *ch)
{
- MEMORY_BASIC_INFORMATION m;
- memset (&m, 0, sizeof m);
- if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
- system_printf ("couldn't get memory info, %E");
-
- ch.stacktop = m.AllocationBase;
- ch.stackbottom = (LPBYTE) m.BaseAddress + m.RegionSize;
- ch.stacksize = (DWORD) ch.stackbottom - (DWORD) &m;
+ 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
diff --git a/winsup/cygwin/init.cc b/winsup/cygwin/init.cc
index 96dda7c1e..655d89160 100644
--- a/winsup/cygwin/init.cc
+++ b/winsup/cygwin/init.cc
@@ -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