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-12-17 07:36:39 +0300
committerChristopher Faylor <me@cgf.cx>2005-12-17 07:36:39 +0300
commitad02bb70e389235036436b8d3f3983b0cd5c1320 (patch)
treec13b960245c056b3e8d88e8bd718b773ea3034bb
parenta249fd1c9b238c5ff15cfa6bbd879cec9fbd372c (diff)
* winsup.h (child_copy): Change prototype to match new functionality.
* cygheap.cc (cygheap_fixup_in_child): Accommodate new child_copy arguments. * dcrt0.cc (dll_data_start): Move definition here from fork. (dll_data_end): Ditto. (dll_bss_start): Ditto. (dll_bss_end): Ditto. (handle_fork): New function. Called when forked to deal with fork issues and copy data to this process from the parent. (dll_crt0_0): Call handle_fork when _PROC_FORK condition. (dll_crt0): Don't copy user_data when we've forked. Don't zero first element of main_environment ever. (cygwin_dll_init): Ditto. * fork.cc (child_copy): Rename from fork_copy and change arguments so that each pair of things to copy gets its own descriptor. (frok::child): Remove fixup_mmaps_after_fork call here. Move to handle_fork in dcrt0.cc. (frok::parent): Use child_copy rather than fork_copy and accommodate changes in parameters. * exceptions.cc (setup_handler): Delay test of whether we're locked until after GetThreadContext has been called since there are apparently cases where SuspendThread does not cause an immediate thread suspension.
-rw-r--r--winsup/cygwin/ChangeLog27
-rw-r--r--winsup/cygwin/cygheap.cc2
-rw-r--r--winsup/cygwin/dcrt0.cc40
-rw-r--r--winsup/cygwin/exceptions.cc17
-rw-r--r--winsup/cygwin/fork.cc151
-rw-r--r--winsup/cygwin/winsup.h2
6 files changed, 134 insertions, 105 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3ae704320..e2c2c77db 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,32 @@
2005-12-16 Christopher Faylor <cgf@timesys.com>
+ * winsup.h (child_copy): Change prototype to match new functionality.
+ * cygheap.cc (cygheap_fixup_in_child): Accommodate new child_copy
+ arguments.
+ * dcrt0.cc (dll_data_start): Move definition here from fork.
+ (dll_data_end): Ditto.
+ (dll_bss_start): Ditto.
+ (dll_bss_end): Ditto.
+ (handle_fork): New function. Called when forked to deal with fork
+ issues and copy data to this process from the parent.
+ (dll_crt0_0): Call handle_fork when _PROC_FORK condition.
+ (dll_crt0): Don't copy user_data when we've forked. Don't zero first
+ element of main_environment ever.
+ (cygwin_dll_init): Ditto.
+ * fork.cc (child_copy): Rename from fork_copy and change arguments so
+ that each pair of things to copy gets its own descriptor.
+ (frok::child): Remove fixup_mmaps_after_fork call here. Move to
+ handle_fork in dcrt0.cc.
+ (frok::parent): Use child_copy rather than fork_copy and accommodate
+ changes in parameters.
+
+ * exceptions.cc (setup_handler): Delay test of whether we're locked
+ until after GetThreadContext has been called since there are apparently
+ cases where SuspendThread does not cause an immediate thread
+ suspension.
+
+2005-12-16 Christopher Faylor <cgf@timesys.com>
+
* init.cc (dll_entry): Call prime_threads after dll_crt0_0 to avoid
conflicts between heap allocation and thread stack allocation.
diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc
index cf64684b1..122e6207a 100644
--- a/winsup/cygwin/cygheap.cc
+++ b/winsup/cygwin/cygheap.cc
@@ -59,7 +59,7 @@ cygheap_fixup_in_child (bool execed)
cygheap_max = child_proc_info->cygheap;
cygheap = (init_cygheap *) cygheap_max;
_csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap);
- child_copy (child_proc_info->parent, child_proc_info->dwProcessId, "cygheap", cygheap, cygheap_max);
+ child_copy (child_proc_info->parent, false, "cygheap", cygheap, cygheap_max, NULL);
cygheap_init ();
debug_fixup_after_fork_exec ();
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 8df5e6e4f..fcff2c324 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -635,6 +635,35 @@ get_cygwin_startup_info ()
return res;
}
+#define dll_data_start &_data_start__
+#define dll_data_end &_data_end__
+#define dll_bss_start &_bss_start__
+#define dll_bss_end &_bss_end__
+
+void
+handle_fork ()
+{
+ alloc_stack (fork_info);
+ cygheap_fixup_in_child (false);
+ memory_init ();
+ set_myself (NULL);
+ HANDLE hp = fork_info->parent;
+ child_copy (hp, false,
+ "dll data", dll_data_start, dll_data_end,
+ "dll bss", dll_bss_start, dll_bss_end,
+ "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
+ NULL);
+ /* step 2 now that the dll has its heap filled in, we can fill in the
+ user's data and bss since user_data is now filled out. */
+ child_copy (hp, false,
+ "data", user_data->data_start, user_data->data_end,
+ "bss", user_data->bss_start, user_data->bss_end,
+ NULL);
+
+ if (fixup_mmaps_after_fork (hp))
+ api_fatal ("recreate_mmaps_after_fork_failed");
+}
+
void __stdcall
dll_crt0_0 ()
{
@@ -675,10 +704,7 @@ dll_crt0_0 ()
switch (child_proc_info->type)
{
case _PROC_FORK:
- alloc_stack (fork_info);
- cygheap_fixup_in_child (false);
- memory_init ();
- set_myself (NULL);
+ handle_fork ();
break;
case _PROC_SPAWN:
case _PROC_EXEC:
@@ -937,7 +963,9 @@ _dll_crt0 ()
system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
main_environ = user_data->envptr;
+#if 0
*main_environ = NULL;
+#endif
char padding[CYGTLS_PADSIZE];
@@ -954,7 +982,7 @@ void
dll_crt0 (per_process *uptr)
{
/* Set the local copy of the pointer into the user space. */
- if (uptr && uptr != user_data)
+ if (!user_data->forkee && uptr && uptr != user_data)
{
memcpy (user_data, uptr, per_process_overwrite);
*(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
@@ -989,7 +1017,9 @@ cygwin_dll_init ()
user_data->fmode_ptr = &_fmode;
main_environ = user_data->envptr;
+#if 0
*main_environ = NULL;
+#endif
initialize_main_tls((char *)&_my_tls);
dll_crt0_1 (NULL);
}
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 4844a02bc..9b989ee9e 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -786,17 +786,12 @@ setup_handler (int sig, void *handler, struct sigaction& siga, _cygtls *tls)
ResumeThread (hth);
break;
}
- if (tls->incyg || tls->spinning || tls->locked ())
- sigproc_printf ("incyg %d, spinning %d, locked %d\n",
- tls->incyg, tls->spinning, tls->locked ());
- else
- {
- cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
- if (!GetThreadContext (hth, &cx))
- system_printf ("couldn't get context of main thread, %E");
- else if (interruptible (cx.Eip))
- interrupted = tls->interrupt_now (&cx, sig, handler, siga);
- }
+ cx.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;
+ if (!GetThreadContext (hth, &cx))
+ system_printf ("couldn't get context of main thread, %E");
+ else if (interruptible (cx.Eip) &&
+ !(tls->incyg || tls->spinning || tls->locked ()))
+ interrupted = tls->interrupt_now (&cx, sig, handler, siga);
res = ResumeThread (hth);
if (interrupted)
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 374eb0fdb..98ef42769 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -37,11 +37,6 @@ details. */
/* FIXME: Once things stabilize, bump up to a few minutes. */
#define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
-#define dll_data_start &_data_start__
-#define dll_data_end &_data_end__
-#define dll_bss_start &_bss_start__
-#define dll_bss_end &_bss_end__
-
class frok
{
dll *first_dll;
@@ -55,60 +50,6 @@ class frok
friend int fork ();
};
-/* Copy memory from parent to child.
- The result is a boolean indicating success. */
-
-static int
-fork_copy (PROCESS_INFORMATION& pi, const char *what, ...)
-{
- va_list args;
- char *low;
- int pass = 0;
-
- va_start (args, what);
-
- while ((low = va_arg (args, char *)))
- {
- char *high = va_arg (args, char *);
- DWORD todo = wincap.chunksize () ?: high - low;
- char *here;
-
- for (here = low; here < high; here += todo)
- {
- DWORD done = 0;
- if (here + todo > high)
- todo = high - here;
- int res;
- if (pi.hThread)
- res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
- else
- res = ReadProcessMemory (pi.hProcess, here, here, todo, &done);
- debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
- low, high, res);
- if (!res || todo != done)
- {
- if (!res)
- __seterrno ();
- /* If this happens then there is a bug in our fork
- implementation somewhere. */
- system_printf ("%s pass %d failed, %p..%p, done %d, windows pid %u, %E",
- what, pass, low, high, done, pi.dwProcessId);
- goto err;
- }
- }
-
- pass++;
- }
-
- debug_printf ("done");
- return 1;
-
- err:
- TerminateProcess (pi.hProcess, 1);
- set_errno (EAGAIN);
- return 0;
-}
-
static int
resume_child (HANDLE forker_finished)
{
@@ -198,9 +139,6 @@ frok::child (void *)
MALLOC_CHECK;
- if (fixup_mmaps_after_fork (hParent))
- api_fatal ("recreate_mmaps_after_fork_failed");
-
#ifdef USE_SERVER
/* Incredible but true: If we use sockets and SYSV IPC shared memory,
there's a good chance that a duplicated socket in the child occupies
@@ -367,7 +305,6 @@ frok::parent (void *stack_here)
goto cleanup;
}
-
/* Fixup the parent datastructure if needed and resume the child's
main thread. */
if (cygheap->fdtab.need_fixup_before ())
@@ -446,22 +383,21 @@ frok::parent (void *stack_here)
MALLOC_CHECK;
- void *impure_beg;
- void *impure_end;
+ const void *impure_beg;
+ const void *impure_end;
+ const char *impure;
if (&_my_tls == _main_tls)
- impure_beg = impure_end = NULL;
+ impure_beg = impure_end = impure = NULL;
else
{
+ impure = "impure";
impure_beg = _impure_ptr;
impure_end = _impure_ptr + 1;
}
- rc = fork_copy (pi, "user/cygwin data",
- user_data->data_start, user_data->data_end,
- user_data->bss_start, user_data->bss_end,
- cygheap->user_heap.base, cygheap->user_heap.ptr,
- stack_here, ch.stackbottom,
- dll_data_start, dll_data_end,
- dll_bss_start, dll_bss_end, impure_beg, impure_end, NULL);
+ rc = child_copy (pi.hProcess, true,
+ "stack", stack_here, ch.stackbottom,
+ impure, impure_beg, impure_end,
+ NULL);
__malloc_unlock ();
locked = false;
@@ -473,9 +409,10 @@ frok::parent (void *stack_here)
for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
{
debug_printf ("copying data/bss of a linked dll");
- 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))
+ if (!child_copy (pi.hProcess, 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
@@ -505,9 +442,10 @@ frok::parent (void *stack_here)
for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
{
debug_printf ("copying data/bss for a loaded dll");
- 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))
+ if (!child_copy (pi.hProcess, 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
@@ -690,13 +628,52 @@ vfork ()
#endif
}
-int
-child_copy (HANDLE h, DWORD pid, const char *what, void *child_start, void *child_end)
+/* Copy memory from one process to another. */
+
+bool
+child_copy (HANDLE hp, bool write, ...)
{
- PROCESS_INFORMATION pi;
- pi.hProcess = h;
- pi.dwProcessId = pid;
- pi.hThread = NULL;
- debug_printf ("%s, start %p, end %p", what, child_start, child_end);
- return fork_copy (pi, what, child_start, child_end, NULL);
+ va_list args;
+ va_start (args, write);
+ static const char *huh[] = {"read", "write"};
+
+ char *what;
+ while ((what = va_arg (args, char *)))
+ {
+ char *low = va_arg (args, char *);
+ char *high = va_arg (args, char *);
+ DWORD todo = wincap.chunksize () ?: high - low;
+ char *here;
+
+ for (here = low; here < high; here += todo)
+ {
+ DWORD done = 0;
+ if (here + todo > high)
+ todo = high - here;
+ int res;
+ if (write)
+ res = WriteProcessMemory (hp, here, here, todo, &done);
+ else
+ res = ReadProcessMemory (hp, here, here, todo, &done);
+ debug_printf ("hp %p, low %p, high %p, res %d", hp, low, high, res);
+ if (!res || todo != done)
+ {
+ if (!res)
+ __seterrno ();
+ /* If this happens then there is a bug in our fork
+ implementation somewhere. */
+ system_printf ("%s %s copy failed, %p..%p, done %d, windows pid %u, %E",
+ what, huh[write], low, high, done);
+ goto err;
+ }
+ }
+ }
+
+ debug_printf ("done");
+ return true;
+
+ err:
+ TerminateProcess (hp, 1);
+ set_errno (EAGAIN);
+ return false;
}
diff --git a/winsup/cygwin/winsup.h b/winsup/cygwin/winsup.h
index d441877eb..72d5aab22 100644
--- a/winsup/cygwin/winsup.h
+++ b/winsup/cygwin/winsup.h
@@ -284,7 +284,7 @@ extern void multiple_cygwin_problem (const char *, unsigned, unsigned);
extern "C" void vklog (int priority, const char *message, va_list ap);
extern "C" void klog (int priority, const char *message, ...);
-int child_copy (HANDLE, DWORD, const char *, void *, void *);
+bool child_copy (HANDLE, bool, ...);
int symlink_worker (const char *, const char *, bool, bool)
__attribute__ ((regparm (3)));