3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
25 #include "child_info.h"
27 #include "perprocess.h"
30 #include "shared_info.h"
31 #include "cygmalloc.h"
32 #include "cygthread.h"
36 /* Timeout to wait for child to start, parent to init child, etc. */
37 /* FIXME: Once things stabilize, bump up to a few minutes. */
38 #define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
48 int __stdcall parent (void *esp);
49 int __stdcall child (void *esp);
54 resume_child (HANDLE forker_finished)
56 SetEvent (forker_finished);
57 debug_printf ("signalled child");
61 /* Notify parent that it is time for the next step. */
63 sync_with_parent (const char *s, bool hang_self)
65 debug_printf ("signalling parent: %s", s);
66 fork_info->ready (false);
69 HANDLE h = fork_info->forker_finished;
70 /* Wait for the parent to fill in our stack and heap.
71 Don't wait forever here. If our parent dies we don't want to clog
72 the system. If the wait fails, we really can't continue so exit. */
73 DWORD psync_rc = WaitForSingleObject (h, FORK_WAIT_TIMEOUT);
74 debug_printf ("awake");
78 api_fatal ("WFSO timed out %s", s);
81 if (GetLastError () == ERROR_INVALID_HANDLE &&
82 WaitForSingleObject (fork_info->forker_finished, 1) != WAIT_FAILED)
84 api_fatal ("WFSO failed %s, fork_finished %p, %E", s,
85 fork_info->forker_finished);
88 debug_printf ("no problems");
97 HANDLE& hParent = ch.parent;
98 extern void fixup_hooks_after_fork ();
99 extern void fixup_timers_after_fork ();
100 debug_printf ("child is running. pid %d, ppid %d, stack here %p",
101 myself->pid, myself->ppid, __builtin_frame_address (0));
103 sync_with_parent ("after longjmp", true);
104 sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d", hParent,
105 first_dll, load_dlls);
107 /* If we've played with the stack, stacksize != 0. That means that
108 fork() was invoked from other than the main thread. Make sure that
109 the threadinfo information is properly set up. */
110 if (fork_info->stacksize)
112 _main_tls = &_my_tls;
113 _main_tls->init_thread (NULL, NULL);
114 _main_tls->local_clib = *_impure_ptr;
115 _impure_ptr = &_main_tls->local_clib;
118 if (wincap.has_security ())
120 set_cygwin_privileges (hProcImpToken);
121 cygheap->user.reimpersonate ();
126 if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
129 /* This is useful for debugging fork problems. Use gdb to attach to
130 the pid reported here. */
131 if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
133 small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
138 set_file_api_mode (current_codepage);
143 /* Incredible but true: If we use sockets and SYSV IPC shared memory,
144 there's a good chance that a duplicated socket in the child occupies
145 memory which is needed to duplicate shared memory from the parent
146 process, if the shared memory hasn't been duplicated already.
147 The same goes very likely for "normal" mmap shared memory, too, but
148 with SYSV IPC it was the first time observed. So, *never* fixup
149 fdtab before fixing up shared memory. */
150 if (fixup_shms_after_fork ())
151 api_fatal ("recreate_shm areas after fork failed");
156 /* If we haven't dynamically loaded any dlls, just signal
157 the parent. Otherwise, load all the dlls, tell the parent
158 that we're done, and wait for the parent to fill in the.
159 loaded dlls' data/bss. */
162 cygheap->fdtab.fixup_after_fork (hParent);
163 sync_with_parent ("performed fork fixup", false);
167 dlls.load_after_fork (hParent, first_dll);
168 cygheap->fdtab.fixup_after_fork (hParent);
169 sync_with_parent ("loaded dlls", true);
172 init_console_handler (myself->ctty >= 0);
173 ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
175 pthread::atforkchild ();
176 fixup_timers_after_fork ();
177 cygbench ("fork-child");
179 fixup_hooks_after_fork ();
180 _my_tls.fixup_after_fork ();
181 wait_for_sigthread (true);
182 cygwin_finished_initializing = true;
186 #define NO_SLOW_PID_REUSE
187 #ifndef NO_SLOW_PID_REUSE
189 slow_pid_reuse (HANDLE h)
191 static NO_COPY HANDLE last_fork_procs[NPIDS_HELD];
192 static NO_COPY unsigned nfork_procs;
194 if (nfork_procs >= (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
196 /* Keep a list of handles to child processes sitting around to prevent
197 Windows from reusing the same pid n times in a row. Having the same pids
198 close in succesion confuses bash. Keeping a handle open will stop
199 windows from reusing the same pid. */
200 if (last_fork_procs[nfork_procs])
201 ForceCloseHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
202 if (DuplicateHandle (hMainProc, h, hMainProc, &last_fork_procs[nfork_procs],
203 0, FALSE, DUPLICATE_SAME_ACCESS))
204 ProtectHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
207 last_fork_procs[nfork_procs] = NULL;
208 system_printf ("couldn't create last_fork_proc, %E");
215 frok::parent (void *stack_here)
217 HANDLE forker_finished;
222 bool fix_impersonation = false;
224 static char errbuf[256];
226 pthread::atforkprepare ();
228 int c_flags = GetPriorityClass (hMainProc);
229 debug_printf ("priority class %d", c_flags);
231 /* If we don't have a console, then don't create a console for the
233 HANDLE console_handle = CreateFile ("CONOUT$", GENERIC_WRITE,
234 FILE_SHARE_WRITE, &sec_none_nih,
235 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
238 if (console_handle != INVALID_HANDLE_VALUE)
239 CloseHandle (console_handle);
241 c_flags |= DETACHED_PROCESS;
243 /* Some file types (currently only sockets) need extra effort in the
244 parent after CreateProcess and before copying the datastructures
245 to the child. So we have to start the child in suspend state,
246 unfortunately, to avoid a race condition. */
247 if (cygheap->fdtab.need_fixup_before ())
248 c_flags |= CREATE_SUSPENDED;
250 /* Remember the address of the first loaded dll and decide
251 if we need to load dlls. We do this here so that this
252 information will be available in the parent and, when
253 the stack is copied, in the child. */
254 first_dll = dlls.start.next;
255 load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
257 /* This will help some of the confusion. */
260 forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
261 if (forker_finished == NULL)
263 this_errno = geterrno_from_win_error ();
264 error = "unable to allocate forker_finished event";
268 ProtectHandleINH (forker_finished);
270 ch.forker_finished = forker_finished;
272 ch.stackbottom = _tlsbase;
273 ch.stacktop = stack_here;
274 ch.stacksize = (char *) ch.stackbottom - (char *) stack_here;
275 debug_printf ("stack - bottom %p, top %p, size %d",
276 ch.stackbottom, ch.stacktop, ch.stacksize);
278 PROCESS_INFORMATION pi;
281 memset (&si, 0, sizeof (si));
282 si.cb = sizeof (STARTUPINFO);
283 si.lpReserved2 = (LPBYTE) &ch;
284 si.cbReserved2 = sizeof (ch);
286 syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %p, 0, 0, %p, %p)",
287 myself->progname, myself->progname, c_flags, &si, &pi);
288 bool locked = __malloc_lock ();
289 time_t start_time = time (NULL);
291 /* Remove impersonation */
292 cygheap->user.deimpersonate ();
293 fix_impersonation = true;
297 rc = CreateProcess (myself->progname, /* image to run */
298 myself->progname, /* what we send in arg0 */
301 TRUE, /* inherit handles from parent */
303 NULL, /* environment filled in later */
304 0, /* use current drive/directory */
310 this_errno = geterrno_from_win_error ();
311 error = "CreateProcessA failed";
312 memset (&pi, 0, sizeof (pi));
316 /* Fixup the parent datastructure if needed and resume the child's
318 if (c_flags & CREATE_SUSPENDED)
320 cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
321 ResumeThread (pi.hThread);
324 CloseHandle (pi.hThread);
326 /* Protect the handle but name it similarly to the way it will
327 be called in subproc handling. */
328 ProtectHandle1 (pi.hProcess, childhProc);
330 strace.write_childpid (ch, pi.dwProcessId);
332 /* Wait for subproc to initialize itself. */
333 if (!ch.sync (pi.dwProcessId, pi.hProcess, FORK_WAIT_TIMEOUT))
335 DWORD exit_code = ch.proc_retry (pi.hProcess);
339 /* Not thread safe, but do we care? */
340 __small_sprintf (errbuf, "died waiting for longjmp before initialization, "
341 "retry %d, exit code %p", ch.retry, exit_code);
348 /* Restore impersonation */
349 cygheap->user.reimpersonate ();
350 fix_impersonation = false;
352 child_pid = cygwin_pid (pi.dwProcessId);
353 child.init (child_pid, 1, NULL);
357 this_errno = get_errno () == ENOMEM ? ENOMEM : EAGAIN;
359 error = "pinfo failed";
361 syscall_printf ("pinfo failed");
366 child->start_time = start_time; /* Register child's starting time. */
367 child->nice = myself->nice;
369 /* Initialize things that are done later in dll_crt0_1 that aren't done
371 strcpy (child->progname, myself->progname);
373 /* Fill in fields in the child's process table entry. */
374 child->dwProcessId = pi.dwProcessId;
375 child.hProcess = pi.hProcess;
377 /* Hopefully, this will succeed. The alternative to doing things this
378 way is to reserve space prior to calling CreateProcess and then fill
379 it in afterwards. This requires more bookkeeping than I like, though,
380 so we'll just do it the easy way. So, terminate any child process if
381 we can't actually record the pid in the internal table. */
382 if (!child.remember (false))
384 TerminateProcess (pi.hProcess, 1);
387 error = "child.remember failed";
392 #ifndef NO_SLOW_PID_REUSE
393 slow_pid_reuse (pi.hProcess);
396 /* CHILD IS STOPPED */
397 debug_printf ("child is alive (but stopped)");
399 /* Initialize, in order: stack, dll data, dll bss.
400 data, bss, heap were done earlier (in dcrt0.cc)
401 Note: variables marked as NO_COPY will not be copied since they are
402 placed in a protected segment. */
405 const void *impure_beg;
406 const void *impure_end;
408 if (&_my_tls == _main_tls)
409 impure_beg = impure_end = impure = NULL;
413 impure_beg = _impure_ptr;
414 impure_end = _impure_ptr + 1;
416 rc = child_copy (pi.hProcess, true,
417 "stack", stack_here, ch.stackbottom,
418 impure, impure_beg, impure_end,
426 this_errno = get_errno ();
428 if (!GetExitCodeProcess (pi.hProcess, &exit_code))
429 exit_code = 0xdeadbeef;
430 __small_sprintf (errbuf, "pid %u, exitval %p", pi.dwProcessId, exit_code);
435 /* Now fill data/bss of any DLLs that were linked into the program. */
436 for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
438 debug_printf ("copying data/bss of a linked dll");
439 if (!child_copy (pi.hProcess, true,
440 "linked dll data", d->p.data_start, d->p.data_end,
441 "linked dll bss", d->p.bss_start, d->p.bss_end,
444 this_errno = get_errno ();
447 if (!GetExitCodeProcess (pi.hProcess, &exit_code))
448 exit_code = 0xdeadbeef;
449 __small_sprintf (errbuf, "pid %u, exitval %p", pi.dwProcessId, exit_code);
456 /* Start thread, and then wait for it to reload dlls. */
457 resume_child (forker_finished);
458 if (!ch.sync (child->pid, pi.hProcess, FORK_WAIT_TIMEOUT))
461 error = "died waiting for dll loading";
465 /* If DLLs were loaded in the parent, then the child has reloaded all
466 of them and is now waiting to have all of the individual data and
467 bss sections filled in. */
470 /* CHILD IS STOPPED */
471 /* write memory of reloaded dlls */
472 for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
474 debug_printf ("copying data/bss for a loaded dll");
475 if (!child_copy (pi.hProcess, true,
476 "loaded dll data", d->p.data_start, d->p.data_end,
477 "loaded dll bss", d->p.bss_start, d->p.bss_end,
480 this_errno = get_errno ();
482 error = "copying data/bss for a loaded dll";
487 /* Start the child up again. */
488 resume_child (forker_finished);
491 ForceCloseHandle (forker_finished);
492 forker_finished = NULL;
493 pthread::atforkparent ();
497 /* Common cleanup code for failure cases */
499 if (fix_impersonation)
500 cygheap->user.reimpersonate ();
504 /* Remember to de-allocate the fd table. */
505 if (pi.hProcess && !child.hProcess)
506 ForceCloseHandle1 (pi.hProcess, childhProc);
508 ForceCloseHandle (forker_finished);
509 debug_printf ("returning -1");
519 debug_printf ("entering");
520 grouped.first_dll = NULL;
521 grouped.load_dlls = 0;
526 myself->set_has_pgid_children ();
528 if (grouped.ch.parent == NULL)
530 if (grouped.ch.subproc_ready == NULL)
532 system_printf ("unable to allocate subproc_ready event, %E");
537 if (sig_send (NULL, __SIGHOLD))
545 ischild = setjmp (grouped.ch.jmp);
548 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
552 res = grouped.child (esp);
557 res = grouped.parent (esp);
558 sig_send (NULL, __SIGNOHOLD);
562 if (ischild || res > 0)
563 /* everything is ok */;
567 syscall_printf ("fork failed - child pid %d, errno %d", grouped.child_pid, grouped.this_errno);
570 char buf[strlen (grouped.error) + sizeof ("child %d - , errno 4294967295 ")];
571 strcpy (buf, "child %d - ");
572 strcat (buf, grouped.error);
573 strcat (buf, ", errno %d");
574 system_printf (buf, grouped.child_pid, grouped.this_errno);
577 set_errno (grouped.this_errno);
579 syscall_printf ("%d = fork()", res);
590 /* Dummy function to force second assignment below to actually be
595 return vfork_storage.val ();
603 debug_printf ("stub called");
606 vfork_save *vf = get_vfork_val ();
610 vf = vfork_storage.create ();
614 // FIXME the tls stuff could introduce a signal race if a child process
619 __asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
620 __asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
621 for (pp = (char **) vf->frame, esp = vf->vfork_esp;
622 esp <= vf->vfork_ebp + 2; pp++, esp++)
624 vf->ctty = myself->ctty;
625 vf->sid = myself->sid;
626 vf->pgid = myself->pgid;
627 cygheap->ctty_on_hold = cygheap->ctty;
628 vf->console_count = cygheap->console_count;
629 debug_printf ("cygheap->ctty_on_hold %p, cygheap->console_count %d", cygheap->ctty_on_hold, cygheap->console_count);
630 int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
631 debug_printf ("%d = vfork()", res);
632 _my_tls.call_signal_handler (); // FIXME: racy
637 vf = get_vfork_val ();
639 for (pp = (char **) vf->frame, esp = vf->vfork_esp;
640 esp <= vf->vfork_ebp + 2; pp++, esp++)
643 cygheap->fdtab.vfork_parent_restore ();
645 myself->ctty = vf->ctty;
646 myself->sid = vf->sid;
647 myself->pgid = vf->pgid;
648 termios_printf ("cygheap->ctty %p, cygheap->ctty_on_hold %p", cygheap->ctty, cygheap->ctty_on_hold);
649 cygheap->console_count = vf->console_count;
653 int exitval = vf->exitval;
655 if ((vf->pid = fork ()) == 0)
661 debug_printf ("exiting vfork, pid %d", pid);
662 sig_dispatch_pending ();
664 _my_tls.call_signal_handler (); // FIXME: racy
670 /* Copy memory from one process to another. */
673 child_copy (HANDLE hp, bool write, ...)
676 va_start (args, write);
677 static const char *huh[] = {"read", "write"};
680 while ((what = va_arg (args, char *)))
682 char *low = va_arg (args, char *);
683 char *high = va_arg (args, char *);
684 DWORD todo = wincap.chunksize () ?: high - low;
687 for (here = low; here < high; here += todo)
690 if (here + todo > high)
694 res = WriteProcessMemory (hp, here, here, todo, &done);
696 res = ReadProcessMemory (hp, here, here, todo, &done);
697 debug_printf ("%s - hp %p low %p, high %p, res %d", what, hp, low, high, res);
698 if (!res || todo != done)
702 /* If this happens then there is a bug in our fork
703 implementation somewhere. */
704 system_printf ("%s %s copy failed, %p..%p, done %d, windows pid %u, %E",
705 what, huh[write], low, high, done);
711 debug_printf ("done");
715 TerminateProcess (hp, 1);