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:
Diffstat (limited to 'winsup/cygwin/fork.cc')
-rw-r--r--winsup/cygwin/fork.cc81
1 files changed, 48 insertions, 33 deletions
diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc
index 54c668137..fdd63c6e3 100644
--- a/winsup/cygwin/fork.cc
+++ b/winsup/cygwin/fork.cc
@@ -280,6 +280,13 @@ fork ()
return -1;
}
+ /* Remember the address of the first loaded dll and decide
+ if we need to load dlls. We do this here so that this
+ information will be available in the parent and, when
+ the stack is copied, in the child. */
+ dll *first_dll = dlls.start.next;
+ int load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
+
static child_info_fork ch;
x = setjmp (ch.jmp);
@@ -457,43 +464,41 @@ fork ()
if (!rc)
goto cleanup;
- /* Now fill data/bss of linked dll */
- DO_LINKED_DLL (p)
- {
- debug_printf ("copying data/bss of a linked dll");
- if (!fork_copy (pi, "linked dll data/bss", p->data_start, p->data_end,
- p->bss_start, p->bss_end,
- NULL))
- goto cleanup;
- }
- DLL_DONE;
+ /* Now fill data/bss of any DLLs that were linked into the program. */
+ 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))
+ goto cleanup;
+ }
proc_register (child);
- int load_dll = DllList::the().forkeeMustReloadDlls() &&
- DllList::the().numberOfOpenedDlls();
/* Start thread, and wait for it to reload dlls. */
if (!resume_child (pi, forker_finished) ||
- !sync_with_child (pi, subproc_ready, load_dll, "child loading dlls"))
+ !sync_with_child (pi, subproc_ready, load_dlls, "child loading dlls"))
goto cleanup;
- /* child reload dlls & then write their data and bss */
- if (load_dll)
- {
- /* CHILD IS STOPPED */
- /* write memory of reloaded dlls */
- DO_LOADED_DLL (p)
+ /* If DLLs were loaded in the parent, then the child has reloaded all
+ of them and is now waiting to have all of the individual data and
+ bss sections filled in. */
+ if (load_dlls)
{
- debug_printf ("copying data/bss for a loaded dll");
- if (!fork_copy (pi, "loaded dll data/bss", p->data_start, p->data_end,
- p->bss_start, p->bss_end,
- NULL))
- goto cleanup;
+ /* CHILD IS STOPPED */
+ /* write memory of reloaded dlls */
+ 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))
+ goto cleanup;
+ }
+ /* Start the child up again. */
+ (void) resume_child (pi, forker_finished);
}
- DLL_DONE;
- /* Start the child up again. */
- (void) resume_child (pi, forker_finished);
- }
ForceCloseHandle (subproc_ready);
ForceCloseHandle (pi.hThread);
@@ -532,6 +537,14 @@ fork ()
char c;
if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
try_to_debug ();
+ char buf[80];
+ /* This is useful for debugging fork problems. Use gdb to attach to
+ the pid reported here. */
+ if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
+ {
+ small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
+ Sleep (atoi(buf));
+ }
#endif
/* If we've played with the stack, stacksize != 0. That means that
@@ -548,20 +561,22 @@ fork ()
dtable.fixup_after_fork (hParent);
signal_fixup_after_fork ();
- ForceCloseHandle (hParent);
MALLOC_CHECK;
- /* reload dlls if necessary */
- if (!DllList::the().forkeeMustReloadDlls() ||
- !DllList::the().numberOfOpenedDlls())
+ /* If we haven't dynamically loaded any dlls, just signal
+ the parent. Otherwise, load all the dlls, tell the parent
+ that we're done, and wait for the parent to fill in the.
+ loaded dlls' data/bss. */
+ if (!load_dlls)
sync_with_parent ("performed fork fixup.", FALSE);
else
{
- DllList::the().forkeeLoadDlls();
+ dlls.load_after_fork (hParent, first_dll);
sync_with_parent ("loaded dlls", TRUE);
}
+ ForceCloseHandle (hParent);
(void) ForceCloseHandle (child_proc_info->subproc_ready);
(void) ForceCloseHandle (child_proc_info->forker_finished);