3 Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions.
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
25 #include "child_info.h"
27 #include "perthread.h"
28 #include "perprocess.h"
32 DWORD NO_COPY chunksize = 0;
33 /* Timeout to wait for child to start, parent to init child, etc. */
34 /* FIXME: Once things stabilize, bump up to a few minutes. */
35 #define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
37 #define dll_data_start &_data_start__
38 #define dll_data_end &_data_end__
39 #define dll_bss_start &_bss_start__
40 #define dll_bss_end &_bss_end__
43 per_thread::set (void *s)
45 if (s == PER_THREAD_FORK_CLEAR)
50 TlsSetValue (get_tls (), s);
54 stack_base (child_info_fork &ch)
56 MEMORY_BASIC_INFORMATION m;
57 memset (&m, 0, sizeof m);
58 if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
59 system_printf ("couldn't get memory info, %E");
61 ch.stacktop = m.AllocationBase;
62 ch.stackbottom = (LPBYTE) m.BaseAddress + m.RegionSize;
63 ch.stacksize = (DWORD) ch.stackbottom - (DWORD) &m;
64 debug_printf ("bottom %p, top %p, stack %p, size %d, reserve %d",
65 ch.stackbottom, ch.stacktop, &m, ch.stacksize,
66 (DWORD) ch.stackbottom - (DWORD) ch.stacktop);
69 /* Copy memory from parent to child.
70 The result is a boolean indicating success. */
73 fork_copy (PROCESS_INFORMATION &pi, const char *what, ...)
79 va_start (args, what);
81 while ((low = va_arg (args, char *)))
83 char *high = va_arg (args, char *);
84 DWORD todo = chunksize ?: high - low;
87 for (here = low; here < high; here += todo)
90 if (here + todo > high)
92 int res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
93 debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
95 if (!res || todo != done)
99 /* If this happens then there is a bug in our fork
100 implementation somewhere. */
101 system_printf ("%s pass %d failed, %p..%p, done %d, %E",
102 what, pass, low, high, done);
110 debug_printf ("done");
114 TerminateProcess (pi.hProcess, 1);
119 /* Wait for child to finish what it's doing and signal us.
120 We don't want to wait forever here.If there's a problem somewhere
121 it'll hang the entire system (since all forks are mutex'd). If we
122 time out, set errno = EAGAIN and hope the app tries again. */
124 sync_with_child (PROCESS_INFORMATION &pi, HANDLE subproc_ready,
125 BOOL hang_child, const char *s)
127 /* We also add the child process handle to the wait. If the child fails
128 to initialize (eg. because of a missing dll). Then this
129 handle will become signalled. This stops a *looong* timeout wait.
133 debug_printf ("waiting for child. reason: %s, hang_child %d", s,
136 w4[0] = subproc_ready;
137 DWORD rc = WaitForMultipleObjects (2, w4, FALSE, FORK_WAIT_TIMEOUT);
139 if (rc == WAIT_OBJECT_0 ||
140 WaitForSingleObject (subproc_ready, 0) == WAIT_OBJECT_0)
142 else if (rc == WAIT_FAILED || rc == WAIT_TIMEOUT)
144 if (rc != WAIT_FAILED)
145 system_printf ("WaitForMultipleObjects timed out");
147 system_printf ("WaitForMultipleObjects failed, %E");
149 syscall_printf ("-1 = fork(), WaitForMultipleObjects failed");
150 TerminateProcess (pi.hProcess, 1);
155 /* Child died. Clean up and exit. */
157 GetExitCodeProcess (pi.hProcess, &errcode);
158 /* Fix me. This is not enough. The fork should not be considered
159 * to have failed if the process was essentially killed by a signal.
161 if (errcode != STATUS_CONTROL_C_EXIT)
163 system_printf ("child %d(%p) died before initialization with status code %p",
164 pi.dwProcessId, pi.hProcess, errcode);
165 system_printf ("*** child state %s", s);
171 syscall_printf ("Child died before subproc_ready signalled");
175 debug_printf ("child signalled me");
180 resume_child (PROCESS_INFORMATION &pi, HANDLE forker_finished)
182 SetEvent (forker_finished);
183 debug_printf ("signalled child");
187 /* Notify parent that it is time for the next step.
188 Note that this has to be a macro since the parent may be messing with
190 static void __stdcall
191 sync_with_parent(const char *s, bool hang_self)
193 debug_printf ("signalling parent: %s", s);
194 /* Tell our parent we're waiting. */
195 if (!SetEvent (child_proc_info->subproc_ready))
196 api_fatal ("fork child - SetEvent failed, %E");
199 HANDLE h = child_proc_info->forker_finished;
200 /* Wait for the parent to fill in our stack and heap.
201 Don't wait forever here. If our parent dies we don't want to clog
202 the system. If the wait fails, we really can't continue so exit. */
203 DWORD psync_rc = WaitForSingleObject (h, FORK_WAIT_TIMEOUT);
204 debug_printf ("awake");
208 api_fatal ("WFSO timed out");
211 if (GetLastError () == ERROR_INVALID_HANDLE &&
212 WaitForSingleObject (child_proc_info->forker_finished, 1) != WAIT_FAILED)
214 api_fatal ("WFSO failed, fork_finished %p, %E", child_proc_info->forker_finished);
217 debug_printf ("no problems");
224 fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
226 debug_printf ("child is running. pid %d, ppid %d, stack here %p",
227 myself->pid, myself->ppid, __builtin_frame_address (0));
229 /* Restore the inheritance state as in parent
230 Don't call setuid here! The flags are already set. */
231 if (myself->impersonated)
233 debug_printf ("Impersonation of child, token: %d", myself->token);
234 if (myself->token == INVALID_HANDLE_VALUE)
235 RevertToSelf (); // probably not needed
236 else if (!ImpersonateLoggedOnUser (myself->token))
237 system_printf ("Impersonate for forked child failed: %E");
240 sync_with_parent ("after longjmp.", TRUE);
241 ProtectHandle (hParent);
242 sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d\n", hParent, first_dll, load_dlls);
246 if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
249 /* This is useful for debugging fork problems. Use gdb to attach to
250 the pid reported here. */
251 if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
253 small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
258 /* If we've played with the stack, stacksize != 0. That means that
259 fork() was invoked from other than the main thread. Make sure that
260 when the "main" thread exits it calls do_exit, like a normal process.
261 Exit with a status code of 0. */
262 if (child_proc_info->stacksize)
264 ((DWORD *)child_proc_info->stackbottom)[-17] = (DWORD)do_exit;
265 ((DWORD *)child_proc_info->stackbottom)[-15] = (DWORD)0;
270 pinfo_fixup_after_fork ();
271 fdtab.fixup_after_fork (hParent);
272 signal_fixup_after_fork ();
276 /* If we haven't dynamically loaded any dlls, just signal
277 the parent. Otherwise, load all the dlls, tell the parent
278 that we're done, and wait for the parent to fill in the.
279 loaded dlls' data/bss. */
281 sync_with_parent ("performed fork fixup.", FALSE);
284 dlls.load_after_fork (hParent, first_dll);
285 sync_with_parent ("loaded dlls", TRUE);
288 ForceCloseHandle (hParent);
289 (void) ForceCloseHandle (child_proc_info->subproc_ready);
290 (void) ForceCloseHandle (child_proc_info->forker_finished);
292 if (recreate_mmaps_after_fork (myself->mmap_ptr))
293 api_fatal ("recreate_mmaps_after_fork_failed");
295 /* Set thread local stuff to zero. Under Windows 95/98 this is sometimes
296 non-zero, for some reason.
297 FIXME: There is a memory leak here after a fork. */
298 for (per_thread **t = threadstuff; *t; t++)
299 if ((*t)->clear_on_fork ())
302 /* Initialize signal/process handling */
304 cygbench ("fork-child");
309 fork_parent (void *stack_here, HANDLE& hParent, dll *&first_dll, bool& load_dlls, child_info_fork &ch)
311 HANDLE subproc_ready, forker_finished;
313 PROCESS_INFORMATION pi = {0, NULL, 0, 0};
314 static NO_COPY HANDLE last_fork_proc = NULL;
319 /* The ProtectHandle call allocates memory so we need to make sure
320 that enough is set aside here so that the sbrk pointer does not
321 move when ProtectHandle is called after the child is started.
322 Otherwise the sbrk pointers in the parent will not agree with
323 the child and when user_data is (regrettably) copied over,
324 the user_data->ptr field will not be accurate. */
325 free (malloc (4096));
328 int c_flags = GetPriorityClass (hMainProc) /*|
329 CREATE_NEW_PROCESS_GROUP*/;
330 STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
332 /* If we don't have a console, then don't create a console for the
334 HANDLE console_handle = CreateFileA ("CONOUT$", GENERIC_WRITE,
335 FILE_SHARE_WRITE, &sec_none_nih,
336 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
339 if (console_handle != INVALID_HANDLE_VALUE && console_handle != 0)
340 CloseHandle (console_handle);
342 c_flags |= DETACHED_PROCESS;
345 if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &hParent, 0, 1,
346 DUPLICATE_SAME_ACCESS))
348 system_printf ("couldn't create handle to myself for child, %E");
352 /* Remember the address of the first loaded dll and decide
353 if we need to load dlls. We do this here so that this
354 information will be available in the parent and, when
355 the stack is copied, in the child. */
356 first_dll = dlls.start.next;
357 load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
359 /* This will help some of the confusion. */
362 subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
363 if (subproc_ready == NULL)
365 CloseHandle (hParent);
366 system_printf ("unable to allocate subproc_ready event, %E");
369 forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
370 if (forker_finished == NULL)
372 CloseHandle (hParent);
373 CloseHandle (subproc_ready);
374 system_printf ("unable to allocate subproc_ready event, %E");
378 ProtectHandle (subproc_ready);
379 ProtectHandle (forker_finished);
381 init_child_info (PROC_FORK1, &ch, 1, subproc_ready);
383 ch.forker_finished = forker_finished;
384 ch.heaptop = user_data->heaptop;
385 ch.heapbase = user_data->heapbase;
386 ch.heapptr = user_data->heapptr;
390 si.cb = sizeof (STARTUPINFO);
391 si.lpReserved2 = (LPBYTE)&ch;
392 si.cbReserved2 = sizeof(ch);
394 /* Remove impersonation */
397 if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
398 seteuid (myself->orig_uid);
401 ch.cygheap = cygheap;
402 ch.cygheap_max = cygheap_max;
405 syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
406 myself->progname, myself->progname, c_flags, &si, &pi);
407 rc = CreateProcess (myself->progname, /* image to run */
408 myself->progname, /* what we send in arg0 */
409 allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
410 allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
411 TRUE, /* inherit handles from parent */
413 NULL, /* environment filled in later */
414 0, /* use current drive/directory */
418 CloseHandle (hParent);
423 syscall_printf ("CreateProcessA failed, %E");
424 ForceCloseHandle(subproc_ready);
425 ForceCloseHandle(forker_finished);
426 /* Restore impersonation */
427 if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
432 pinfo forked (cygwin_pid (pi.dwProcessId), 1);
434 /* Initialize things that are done later in dll_crt0_1 that aren't done
436 strcpy(forked->progname, myself->progname);
438 /* Restore impersonation */
439 if (myself->impersonated && myself->token != INVALID_HANDLE_VALUE)
442 ProtectHandle (pi.hThread);
443 /* Protect the handle but name it similarly to the way it will
444 be called in subproc handling. */
445 ProtectHandle1 (pi.hProcess, childhProc);
447 /* Keep a handle to the current forked process sitting around to prevent
448 Windows from reusing the same pid twice in a row. Having the same pid
449 twice in a row confuses bash. So, after every CreateProcess, we can safely
450 remove the old pid and save a handle to the newly created process. Keeping
451 a handle open will stop windows from reusing the same pid. */
453 CloseHandle (last_fork_proc);
454 if (!DuplicateHandle (hMainProc, pi.hProcess, hMainProc, &last_fork_proc,
455 0, FALSE, DUPLICATE_SAME_ACCESS))
456 system_printf ("couldn't create last_fork_proc, %E");
458 /* Fill in fields in the child's process table entry. */
459 forked->ppid = myself->pid;
460 forked->hProcess = pi.hProcess;
461 forked->dwProcessId = pi.dwProcessId;
462 forked->uid = myself->uid;
463 forked->gid = myself->gid;
464 forked->pgid = myself->pgid;
465 forked->sid = myself->sid;
466 forked->ctty = myself->ctty;
467 forked->umask = myself->umask;
468 forked->copysigs(myself);
469 forked->process_state |= PID_INITIALIZING |
470 (myself->process_state & PID_USETTY);
471 memcpy (forked->username, myself->username, MAX_USER_NAME);
472 if (myself->use_psid)
474 memcpy (forked->psid, myself->psid, MAX_SID_LEN);
475 forked->use_psid = 1;
477 memcpy (forked->logsrv, myself->logsrv, MAX_HOST_NAME);
478 memcpy (forked->domain, myself->domain, MAX_COMPUTERNAME_LENGTH+1);
479 forked->token = myself->token;
480 forked->impersonated = myself->impersonated;
481 forked->orig_uid = myself->orig_uid;
482 forked->orig_gid = myself->orig_gid;
483 forked->real_uid = myself->real_uid;
484 forked->real_gid = myself->real_gid;
485 strcpy (forked->root, myself->root);
486 forked->rootlen = myself->rootlen;
487 set_child_mmap_ptr (forked);
489 /* Wait for subproc to initialize itself. */
490 if (!sync_with_child(pi, subproc_ready, TRUE, "waiting for longjmp"))
493 /* CHILD IS STOPPED */
494 debug_printf ("child is alive (but stopped)");
496 /* Initialize, in order: data, bss, heap, stack, dll data, dll bss
497 Note: variables marked as NO_COPY will not be copied
498 since they are placed in a protected segment. */
502 rc = fork_copy (pi, "user/cygwin data",
503 user_data->data_start, user_data->data_end,
504 user_data->bss_start, user_data->bss_end,
505 ch.heapbase, ch.heapptr,
506 stack_here, ch.stackbottom,
507 dll_data_start, dll_data_end,
508 dll_bss_start, dll_bss_end, NULL);
514 /* Now fill data/bss of any DLLs that were linked into the program. */
515 for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
517 debug_printf ("copying data/bss of a linked dll");
518 if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,
519 d->p.bss_start, d->p.bss_end,
526 /* Start thread, and wait for it to reload dlls. */
527 if (!resume_child (pi, forker_finished) ||
528 !sync_with_child (pi, subproc_ready, load_dlls, "child loading dlls"))
531 /* If DLLs were loaded in the parent, then the child has reloaded all
532 of them and is now waiting to have all of the individual data and
533 bss sections filled in. */
536 /* CHILD IS STOPPED */
537 /* write memory of reloaded dlls */
538 for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
540 debug_printf ("copying data/bss for a loaded dll");
541 if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,
542 d->p.bss_start, d->p.bss_end,
546 /* Start the child up again. */
547 (void) resume_child (pi, forker_finished);
550 ForceCloseHandle (subproc_ready);
551 ForceCloseHandle (pi.hThread);
552 ForceCloseHandle (forker_finished);
553 forker_finished = NULL;
558 /* Common cleanup code for failure cases */
560 /* Remember to de-allocate the fd table. */
562 ForceCloseHandle1 (pi.hProcess, childhProc);
564 ForceCloseHandle (pi.hThread);
566 ForceCloseHandle (subproc_ready);
568 ForceCloseHandle (forker_finished);
584 debug_printf ("entering");
585 grouped.hParent = grouped.first_dll = NULL;
586 grouped.load_dlls = 0;
588 if (ISSTATE(myself, PID_SPLIT_HEAP))
590 system_printf ("The heap has been split, CYGWIN can't fork this process.");
591 system_printf ("Increase the heap_chunk_size in the registry and try again.");
593 syscall_printf ("-1 = fork (), split heap");
598 __asm ("movl %%esp,%0": "=r" (esp));
602 int res = setjmp (ch.jmp);
605 res = fork_child (grouped.hParent, grouped.first_dll, grouped.load_dlls);
607 res = fork_parent (esp, grouped.hParent, grouped.first_dll, grouped.load_dlls, ch);
610 syscall_printf ("%d = fork()", res);
615 /* Dummy function to force second assignment below to actually be
620 return vfork_storage.val ();
631 vfork_save *vf = get_vfork_val ();
635 vf = vfork_storage.create ();
640 __asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
641 __asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
642 for (pp = (char **)vf->frame, esp = vf->vfork_esp;
643 esp <= vf->vfork_ebp + 1; pp++, esp++)
645 return fdtab.vfork_child_dup () ? 0 : -1;
648 fdtab.vfork_parent_restore ();
650 vf = get_vfork_val ();
653 int exitval = -vf->pid;
654 if ((vf->pid = fork ()) == 0)
658 __asm__ volatile ("movl %%esp,%0": "=r" (esp):);
659 for (pp = (char **)vf->frame, esp = vf->vfork_esp;
660 esp <= vf->vfork_ebp + 1; pp++, esp++)