3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
24 #include "child_info.h"
26 #include "perprocess.h"
29 #include "shared_info.h"
30 #include "cygmalloc.h"
31 #include "cygthread.h"
35 /* Timeout to wait for child to start, parent to init child, etc. */
36 /* FIXME: Once things stabilize, bump up to a few minutes. */
37 #define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
39 #define dll_data_start &_data_start__
40 #define dll_data_end &_data_end__
41 #define dll_bss_start &_bss_start__
42 #define dll_bss_end &_bss_end__
45 stack_base (child_info_fork &ch)
47 MEMORY_BASIC_INFORMATION m;
48 memset (&m, 0, sizeof m);
49 if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
50 system_printf ("couldn't get memory info, %E");
52 ch.stacktop = m.AllocationBase;
53 ch.stackbottom = (LPBYTE) m.BaseAddress + m.RegionSize;
54 ch.stacksize = (DWORD) ch.stackbottom - (DWORD) &m;
55 debug_printf ("bottom %p, top %p, stack %p, size %d, reserve %d",
56 ch.stackbottom, ch.stacktop, &m, ch.stacksize,
57 (DWORD) ch.stackbottom - (DWORD) ch.stacktop);
60 /* Copy memory from parent to child.
61 The result is a boolean indicating success. */
64 fork_copy (PROCESS_INFORMATION &pi, const char *what, ...)
70 va_start (args, what);
72 while ((low = va_arg (args, char *)))
74 char *high = va_arg (args, char *);
75 DWORD todo = wincap.chunksize () ?: high - low;
78 for (here = low; here < high; here += todo)
81 if (here + todo > high)
83 int res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
84 debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
86 if (!res || todo != done)
90 /* If this happens then there is a bug in our fork
91 implementation somewhere. */
92 system_printf ("%s pass %d failed, %p..%p, done %d, windows pid %u, %E",
93 what, pass, low, high, done, pi.dwProcessId);
101 debug_printf ("done");
105 TerminateProcess (pi.hProcess, 1);
111 resume_child (HANDLE forker_finished)
113 SetEvent (forker_finished);
114 debug_printf ("signalled child");
118 /* Notify parent that it is time for the next step.
119 Note that this has to be a macro since the parent may be messing with
121 static void __stdcall
122 sync_with_parent (const char *s, bool hang_self)
124 debug_printf ("signalling parent: %s", s);
125 fork_info->ready (false);
128 HANDLE h = fork_info->forker_finished;
129 /* Wait for the parent to fill in our stack and heap.
130 Don't wait forever here. If our parent dies we don't want to clog
131 the system. If the wait fails, we really can't continue so exit. */
132 DWORD psync_rc = WaitForSingleObject (h, FORK_WAIT_TIMEOUT);
133 debug_printf ("awake");
137 api_fatal ("WFSO timed out %s", s);
140 if (GetLastError () == ERROR_INVALID_HANDLE &&
141 WaitForSingleObject (fork_info->forker_finished, 1) != WAIT_FAILED)
143 api_fatal ("WFSO failed %s, fork_finished %p, %E", s,
144 fork_info->forker_finished);
147 debug_printf ("no problems");
154 fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
156 extern void fixup_timers_after_fork ();
157 debug_printf ("child is running. pid %d, ppid %d, stack here %p",
158 myself->pid, myself->ppid, __builtin_frame_address (0));
160 /* Restore the inheritance state as in parent
161 Don't call setuid here! The flags are already set. */
162 cygheap->user.reimpersonate ();
164 sync_with_parent ("after longjmp", true);
165 sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d", hParent,
166 first_dll, load_dlls);
168 /* If we've played with the stack, stacksize != 0. That means that
169 fork() was invoked from other than the main thread. Make sure that
170 the threadinfo information is properly set up. */
171 if (fork_info->stacksize)
173 _main_tls = &_my_tls;
174 _main_tls->init_thread (NULL, NULL);
175 _main_tls->local_clib = *_impure_ptr;
176 _impure_ptr = &_main_tls->local_clib;
181 if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
184 /* This is useful for debugging fork problems. Use gdb to attach to
185 the pid reported here. */
186 if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
188 small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
193 set_file_api_mode (current_codepage);
197 if (fixup_mmaps_after_fork (hParent))
198 api_fatal ("recreate_mmaps_after_fork_failed");
203 /* If we haven't dynamically loaded any dlls, just signal
204 the parent. Otherwise, load all the dlls, tell the parent
205 that we're done, and wait for the parent to fill in the.
206 loaded dlls' data/bss. */
209 cygheap->fdtab.fixup_after_fork (hParent);
210 ProtectHandleINH (hParent);
211 sync_with_parent ("performed fork fixup", false);
215 dlls.load_after_fork (hParent, first_dll);
216 cygheap->fdtab.fixup_after_fork (hParent);
217 ProtectHandleINH (hParent);
218 sync_with_parent ("loaded dlls", true);
221 ForceCloseHandle (hParent);
222 (void) ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
224 _my_tls.fixup_after_fork ();
228 if (fixup_shms_after_fork ())
229 api_fatal ("recreate_shm areas after fork failed");
232 pthread::atforkchild ();
233 fixup_timers_after_fork ();
234 cygbench ("fork-child");
235 cygwin_finished_initializing = true;
239 #ifndef NO_SLOW_PID_REUSE
241 slow_pid_reuse (HANDLE h)
243 static NO_COPY HANDLE last_fork_procs[NPIDS_HELD] = {0};
244 static NO_COPY unsigned nfork_procs = 0;
246 if (nfork_procs >= (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
248 /* Keep a list of handles to child processes sitting around to prevent
249 Windows from reusing the same pid n times in a row. Having the same pids
250 close in succesion confuses bash. Keeping a handle open will stop
251 windows from reusing the same pid. */
252 if (last_fork_procs[nfork_procs])
253 ForceCloseHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
254 if (DuplicateHandle (hMainProc, h, hMainProc, &last_fork_procs[nfork_procs],
255 0, FALSE, DUPLICATE_SAME_ACCESS))
256 ProtectHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
259 last_fork_procs[nfork_procs] = NULL;
260 system_printf ("couldn't create last_fork_proc, %E");
267 fork_parent (HANDLE& hParent, dll *&first_dll,
268 bool& load_dlls, void *stack_here, child_info_fork &ch)
270 HANDLE forker_finished;
272 PROCESS_INFORMATION pi = {0, NULL, 0, 0};
274 pthread::atforkprepare ();
276 int c_flags = GetPriorityClass (hMainProc) /*|
277 CREATE_NEW_PROCESS_GROUP*/;
278 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
280 /* If we don't have a console, then don't create a console for the
282 HANDLE console_handle = CreateFile ("CONOUT$", GENERIC_WRITE,
283 FILE_SHARE_WRITE, &sec_none_nih,
284 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
287 if (console_handle != INVALID_HANDLE_VALUE)
288 CloseHandle (console_handle);
290 c_flags |= DETACHED_PROCESS;
292 /* Some file types (currently only sockets) need extra effort in the
293 parent after CreateProcess and before copying the datastructures
294 to the child. So we have to start the child in suspend state,
295 unfortunately, to avoid a race condition. */
296 if (cygheap->fdtab.need_fixup_before ())
297 c_flags |= CREATE_SUSPENDED;
299 /* Create an inheritable handle to pass to the child process. This will
300 allow the child to duplicate handles from the parent to itself. */
302 if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, TRUE,
303 DUPLICATE_SAME_ACCESS))
305 system_printf ("couldn't create handle to myself for child, %E");
309 /* Remember the address of the first loaded dll and decide
310 if we need to load dlls. We do this here so that this
311 information will be available in the parent and, when
312 the stack is copied, in the child. */
313 first_dll = dlls.start.next;
314 load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
316 /* This will help some of the confusion. */
319 forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
320 if (forker_finished == NULL)
322 CloseHandle (hParent);
323 system_printf ("unable to allocate forker_finished event, %E");
327 ProtectHandleINH (forker_finished);
329 ch.forker_finished = forker_finished;
333 si.cb = sizeof (STARTUPINFO);
334 si.lpReserved2 = (LPBYTE) &ch;
335 si.cbReserved2 = sizeof (ch);
337 /* Remove impersonation */
338 cygheap->user.deimpersonate ();
342 syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
343 myself->progname, myself->progname, c_flags, &si, &pi);
344 bool locked = __malloc_lock ();
346 newheap = cygheap_setup_for_child (&ch, cygheap->fdtab.need_fixup_before ());
347 rc = CreateProcess (myself->progname, /* image to run */
348 myself->progname, /* what we send in arg0 */
351 TRUE, /* inherit handles from parent */
353 NULL, /* environment filled in later */
354 0, /* use current drive/directory */
358 CloseHandle (hParent);
363 syscall_printf ("CreateProcessA failed, %E");
364 ForceCloseHandle (forker_finished);
365 /* Restore impersonation */
366 cygheap->user.reimpersonate ();
367 cygheap_setup_for_child_cleanup (newheap, &ch, 0);
372 /* Fixup the parent datastructure if needed and resume the child's
374 if (!cygheap->fdtab.need_fixup_before ())
375 cygheap_setup_for_child_cleanup (newheap, &ch, 0);
378 cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
379 cygheap_setup_for_child_cleanup (newheap, &ch, 1);
380 ResumeThread (pi.hThread);
383 int child_pid = cygwin_pid (pi.dwProcessId);
384 pinfo child (child_pid, 1);
385 child->start_time = time (NULL); /* Register child's starting time. */
389 syscall_printf ("pinfo failed");
390 if (get_errno () != ENOMEM)
395 /* Initialize things that are done later in dll_crt0_1 that aren't done
397 strcpy (child->progname, myself->progname);
399 /* Restore impersonation */
400 cygheap->user.reimpersonate ();
402 ProtectHandle (pi.hThread);
403 /* Protect the handle but name it similarly to the way it will
404 be called in subproc handling. */
405 ProtectHandle1 (pi.hProcess, childhProc);
407 /* Fill in fields in the child's process table entry. */
408 child->dwProcessId = pi.dwProcessId;
409 child.hProcess = pi.hProcess;
411 /* Hopefully, this will succeed. The alternative to doing things this
412 way is to reserve space prior to calling CreateProcess and then fill
413 it in afterwards. This requires more bookkeeping than I like, though,
414 so we'll just do it the easy way. So, terminate any child process if
415 we can't actually record the pid in the internal table. */
416 if (!child.remember (false))
418 TerminateProcess (pi.hProcess, 1);
423 #ifndef NO_SLOW_PID_REUSE
424 slow_pid_reuse (pi.hProcess);
427 /* Wait for subproc to initialize itself. */
428 if (!ch.sync (child, FORK_WAIT_TIMEOUT))
430 system_printf ("child %d died waiting for longjmp before initialization", child_pid);
434 /* CHILD IS STOPPED */
435 debug_printf ("child is alive (but stopped)");
437 /* Initialize, in order: data, bss, heap, stack, dll data, dll bss
438 Note: variables marked as NO_COPY will not be copied
439 since they are placed in a protected segment. */
445 if (&_my_tls == _main_tls)
446 impure_beg = impure_end = NULL;
449 impure_beg = _impure_ptr;
450 impure_end = _impure_ptr + 1;
452 rc = fork_copy (pi, "user/cygwin data",
453 user_data->data_start, user_data->data_end,
454 user_data->bss_start, user_data->bss_end,
455 cygheap->user_heap.base, cygheap->user_heap.ptr,
456 stack_here, ch.stackbottom,
457 dll_data_start, dll_data_end,
458 dll_bss_start, dll_bss_end, impure_beg, impure_end, NULL);
466 /* Now fill data/bss of any DLLs that were linked into the program. */
467 for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
469 debug_printf ("copying data/bss of a linked dll");
470 if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,
471 d->p.bss_start, d->p.bss_end,
476 /* Start thread, and wait for it to reload dlls. */
477 if (!resume_child (forker_finished))
479 else if (!ch.sync (child, FORK_WAIT_TIMEOUT))
481 system_printf ("child %d died waiting for dll loading", child_pid);
485 /* If DLLs were loaded in the parent, then the child has reloaded all
486 of them and is now waiting to have all of the individual data and
487 bss sections filled in. */
490 /* CHILD IS STOPPED */
491 /* write memory of reloaded dlls */
492 for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
494 debug_printf ("copying data/bss for a loaded dll");
495 if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,
496 d->p.bss_start, d->p.bss_end,
500 /* Start the child up again. */
501 (void) resume_child (forker_finished);
504 ForceCloseHandle (pi.hThread);
505 ForceCloseHandle (forker_finished);
506 forker_finished = NULL;
508 pthread::atforkparent ();
512 /* Common cleanup code for failure cases */
517 /* Remember to de-allocate the fd table. */
519 ForceCloseHandle1 (pi.hProcess, childhProc);
521 ForceCloseHandle (pi.hThread);
523 ForceCloseHandle (forker_finished);
539 debug_printf ("entering");
540 grouped.hParent = grouped.first_dll = NULL;
541 grouped.load_dlls = 0;
544 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
546 myself->set_has_pgid_children ();
549 if (ch.subproc_ready == NULL)
551 system_printf ("unable to allocate subproc_ready event, %E");
555 sig_send (NULL, __SIGHOLD);
556 int res = setjmp (ch.jmp);
558 res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls);
560 res = fork_parent (grouped.hParent, grouped.first_dll, grouped.load_dlls, esp, ch);
561 sig_send (NULL, __SIGNOHOLD);
564 syscall_printf ("%d = fork()", res);
575 /* Dummy function to force second assignment below to actually be
580 return vfork_storage.val ();
588 debug_printf ("stub called");
591 vfork_save *vf = get_vfork_val ();
595 vf = vfork_storage.create ();
599 // FIXME the tls stuff could introduce a signal race if a child process
604 __asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
605 __asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
606 for (pp = (char **) vf->frame, esp = vf->vfork_esp;
607 esp <= vf->vfork_ebp + 2; pp++, esp++)
609 vf->ctty = myself->ctty;
610 vf->sid = myself->sid;
611 vf->pgid = myself->pgid;
612 cygheap->ctty_on_hold = cygheap->ctty;
613 vf->open_fhs = cygheap->open_fhs;
614 debug_printf ("cygheap->ctty_on_hold %p, cygheap->open_fhs %d", cygheap->ctty_on_hold, cygheap->open_fhs);
615 int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
616 debug_printf ("%d = vfork()", res);
617 _my_tls.call_signal_handler (); // FIXME: racy
622 vf = get_vfork_val ();
624 for (pp = (char **) vf->frame, esp = vf->vfork_esp;
625 esp <= vf->vfork_ebp + 2; pp++, esp++)
628 cygheap->fdtab.vfork_parent_restore ();
630 myself->ctty = vf->ctty;
631 myself->sid = vf->sid;
632 myself->pgid = vf->pgid;
633 termios_printf ("cygheap->ctty %p, cygheap->ctty_on_hold %p", cygheap->ctty, cygheap->ctty_on_hold);
634 cygheap->open_fhs = vf->open_fhs;
638 int exitval = vf->exitval;
640 if ((vf->pid = fork ()) == 0)
646 debug_printf ("exiting vfork, pid %d", pid);
647 sig_dispatch_pending ();
649 _my_tls.call_signal_handler (); // FIXME: racy