From: cgf Date: Sat, 17 Dec 2005 04:36:38 +0000 (+0000) Subject: * winsup.h (child_copy): Change prototype to match new functionality. X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=400c6dc17e6fd384f9519de35959f113e4a9d4bd;p=pf3gnuchains%2Fpf3gnuchains3x.git * 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. --- diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 3ae7043205..e2c2c77dbd 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,5 +1,32 @@ 2005-12-16 Christopher Faylor + * 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 + * 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 cf64684b10..122e6207a5 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 8df5e6e4f3..fcff2c3240 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 4844a02bcd..9b989ee9e4 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 374eb0fdb5..98ef42769c 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 d441877eba..72d5aab22f 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)));