3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
20 #include "child_info.h"
23 #include "shared_info.h"
25 #include "cygmalloc.h"
30 /* Timeout to wait for child to start, parent to init child, etc. */
31 /* FIXME: Once things stabilize, bump up to a few minutes. */
32 #define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
34 static int dofork (void **proc
, bool *with_forkables
);
37 frok (bool *forkables
)
38 : with_forkables (forkables
)
47 int parent (volatile char * volatile here
);
48 int child (volatile char * volatile here
);
49 bool error (const char *fmt
, ...);
50 friend int dofork (void **proc
, bool *with_forkables
);
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");
95 frok::error (const char *fmt
, ...)
97 DWORD exit_code
= ch
.exit_code
;
98 if (!exit_code
&& hchild
)
100 exit_code
= ch
.proc_retry (hchild
);
104 if (exit_code
!= EXITCODE_FORK_FAILED
)
107 static char buf
[NT_MAX_PATH
+ 256];
109 __small_vsprintf (buf
, fmt
, ap
);
115 /* Set up a pipe which will track the life of a "pid" through
116 even after we've exec'ed. */
118 child_info::prefork (bool detached
)
122 if (!CreatePipe (&rd_proc_pipe
, &wr_proc_pipe
, &sec_none_nih
, 16))
123 api_fatal ("prefork: couldn't create pipe process tracker, %E");
125 if (!SetHandleInformation (wr_proc_pipe
, HANDLE_FLAG_INHERIT
,
126 HANDLE_FLAG_INHERIT
))
127 api_fatal ("prefork: couldn't set process pipe(%p) inherit state, %E",
129 ProtectHandle1 (rd_proc_pipe
, rd_proc_pipe
);
130 ProtectHandle1 (wr_proc_pipe
, wr_proc_pipe
);
135 frok::child (volatile char * volatile here
)
137 HANDLE
& hParent
= ch
.parent
;
139 sync_with_parent ("after longjmp", true);
140 debug_printf ("child is running. pid %d, ppid %d, stack here %p",
141 myself
->pid
, myself
->ppid
, __builtin_frame_address (0));
142 sigproc_printf ("hParent %p, load_dlls %d", hParent
, load_dlls
);
144 /* Make sure threadinfo information is properly set up. */
145 if (&_my_tls
!= _main_tls
)
147 _main_tls
= &_my_tls
;
148 _main_tls
->init_thread (NULL
, NULL
);
151 set_cygwin_privileges (hProcToken
);
152 clear_procimptoken ();
153 cygheap
->user
.reimpersonate ();
156 if (GetEnvironmentVariableA ("FORKDEBUG", NULL
, 0))
159 /* This is useful for debugging fork problems. Use gdb to attach to
160 the pid reported here. */
161 if (GetEnvironmentVariableA ("CYGWIN_FORK_SLEEP", buf
, sizeof (buf
)))
163 small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf
), GetCurrentProcessId ());
168 /* Incredible but true: If we use sockets and SYSV IPC shared memory,
169 there's a good chance that a duplicated socket in the child occupies
170 memory which is needed to duplicate shared memory from the parent
171 process, if the shared memory hasn't been duplicated already.
172 The same goes very likely for "normal" mmap shared memory, too, but
173 with SYSV IPC it was the first time observed. So, *never* fixup
174 fdtab before fixing up shared memory. */
175 if (fixup_shms_after_fork ())
176 api_fatal ("recreate_shm areas after fork failed");
178 /* load dynamic dlls, if any, re-track main-executable and cygwin1.dll */
179 dlls
.load_after_fork (hParent
);
181 cygheap
->fdtab
.fixup_after_fork (hParent
);
183 /* Signal that we have successfully initialized, so the parent can
184 - transfer data/bss for dynamically loaded dlls (if any), or
185 - terminate the current fork call even if the child is initialized. */
186 sync_with_parent ("performed fork fixups and dynamic dll loading", true);
188 ForceCloseHandle1 (fork_info
->forker_finished
, forker_finished
);
190 pthread::atforkchild ();
191 cygbench ("fork-child");
193 fixup_hooks_after_fork ();
194 _my_tls
.fixup_after_fork ();
195 /* Clear this or the destructor will close them. In the case of
196 rd_proc_pipe that would be an invalid handle. In the case of
197 wr_proc_pipe it would be == my_wr_proc_pipe. Both would be bad. */
198 ch
.rd_proc_pipe
= ch
.wr_proc_pipe
= NULL
;
199 CloseHandle (hParent
);
201 cygwin_finished_initializing
= true;
206 frok::parent (volatile char * volatile stack_here
)
208 HANDLE forker_finished
;
212 bool fix_impersonation
= false;
215 int c_flags
= GetPriorityClass (GetCurrentProcess ());
216 debug_printf ("priority class %d", c_flags
);
217 /* Per MSDN, this must be specified even if lpEnvironment is set to NULL,
218 otherwise UNICODE characters in the parent environment are not copied
219 correctly to the child. Omitting it may scramble %PATH% on non-English
221 c_flags
|= CREATE_UNICODE_ENVIRONMENT
;
226 /* If we don't have a console, then don't create a console for the
228 HANDLE console_handle
= CreateFile ("CONOUT$", GENERIC_WRITE
,
229 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
230 &sec_none_nih
, OPEN_EXISTING
,
231 FILE_ATTRIBUTE_NORMAL
, NULL
);
233 if (console_handle
!= INVALID_HANDLE_VALUE
)
234 CloseHandle (console_handle
);
236 c_flags
|= DETACHED_PROCESS
;
238 /* Some file types (currently only sockets) need extra effort in the
239 parent after CreateProcess and before copying the datastructures
240 to the child. So we have to start the child in suspend state,
241 unfortunately, to avoid a race condition. */
242 if (cygheap
->fdtab
.need_fixup_before ())
243 c_flags
|= CREATE_SUSPENDED
;
245 /* Remember if we need to load dynamically linked dlls.
246 We do this here so that this information will be available
247 in the parent and, when the stack is copied, in the child. */
248 load_dlls
= dlls
.reload_on_fork
&& dlls
.loaded_dlls
;
250 forker_finished
= CreateEvent (&sec_all
, FALSE
, FALSE
, NULL
);
251 if (forker_finished
== NULL
)
253 this_errno
= geterrno_from_win_error ();
254 error ("unable to allocate forker_finished event");
258 ProtectHandleINH (forker_finished
);
260 ch
.forker_finished
= forker_finished
;
262 ch
.stackbase
= NtCurrentTeb ()->Tib
.StackBase
;
263 ch
.stackaddr
= NtCurrentTeb ()->DeallocationStack
;
266 /* If DeallocationStack is NULL, we're running on an application-provided
267 stack. If so, the entire stack is committed anyway and StackLimit
268 points to the allocation address of the stack. Mark in guardsize that
269 we must not set up guard pages. */
270 ch
.stackaddr
= ch
.stacklimit
= NtCurrentTeb ()->Tib
.StackLimit
;
271 ch
.guardsize
= (size_t) -1;
275 /* Otherwise we're running on a system-allocated stack. Since stack_here
276 is the address of the stack pointer we start the child with anyway, we
277 can set ch.stacklimit to this value rounded down to page size. The
278 child will not need the rest of the stack anyway. Guardsize depends
279 on whether we're running on a pthread or not. If pthread, we fetch
280 the guardpage size from the pthread attribs, otherwise we use the
282 ch
.stacklimit
= (void *) ((uintptr_t) stack_here
& ~(wincap
.page_size () - 1));
283 ch
.guardsize
= (&_my_tls
!= _main_tls
&& _my_tls
.tid
)
284 ? _my_tls
.tid
->attr
.guardsize
285 : wincap
.def_guard_page_size ();
287 debug_printf ("stack - bottom %p, top %p, addr %p, guardsize %ly",
288 ch
.stackbase
, ch
.stacklimit
, ch
.stackaddr
, ch
.guardsize
);
290 PROCESS_INFORMATION pi
;
293 memset (&si
, 0, sizeof (si
));
296 si
.lpReserved2
= (LPBYTE
) &ch
;
297 si
.cbReserved2
= sizeof (ch
);
299 /* NEVER, EVER, call a function which in turn calls malloc&friends while this
300 malloc lock is active! */
304 /* Remove impersonation */
305 cygheap
->user
.deimpersonate ();
306 fix_impersonation
= true;
307 ch
.refresh_cygheap ();
308 ch
.prefork (); /* set up process tracking pipes. */
310 *with_forkables
= dlls
.setup_forkables (*with_forkables
);
312 ch
.silentfail (!*with_forkables
); /* fail silently without forkables */
314 PSECURITY_ATTRIBUTES sa
= (PSECURITY_ATTRIBUTES
) alloca (1024);
315 if (!sec_user_nih (sa
, cygheap
->user
.saved_sid (),
316 well_known_authenticated_users_sid
,
317 PROCESS_QUERY_LIMITED_INFORMATION
))
322 PCWCHAR forking_progname
= NULL
;
323 if (dlls
.main_executable
)
324 forking_progname
= dll_list::buffered_shortname
325 (dlls
.main_executable
->forkedntname ());
326 if (!forking_progname
|| !*forking_progname
)
327 forking_progname
= myself
->progname
;
329 syscall_printf ("CreateProcessW (%W, %W, 0, 0, 1, %y, 0, 0, %p, %p)",
330 forking_progname
, myself
->progname
, c_flags
, &si
, &pi
);
333 /* cygwin1.dll may reuse the forking_progname buffer, even
334 in case of failure: don't reuse forking_progname later */
335 rc
= CreateProcessW (forking_progname
, /* image to run */
336 GetCommandLineW (), /* Take same space for command
337 line as in parent to make
338 sure child stack is allocated
339 in the same memory location
343 TRUE
, /* inherit handles */
345 NULL
, /* environ filled in later */
351 debug_printf ("forked pid %u", pi
.dwProcessId
);
354 this_errno
= geterrno_from_win_error ();
355 error ("CreateProcessW failed for '%W'", myself
->progname
);
356 dlls
.release_forkables ();
357 memset (&pi
, 0, sizeof (pi
));
361 if (cygheap
->fdtab
.need_fixup_before ())
363 cygheap
->fdtab
.fixup_before_fork (pi
.dwProcessId
);
364 ResumeThread (pi
.hThread
);
367 CloseHandle (pi
.hThread
);
368 hchild
= pi
.hProcess
;
370 dlls
.release_forkables ();
372 /* Protect the handle but name it similarly to the way it will
373 be called in subproc handling. */
374 ProtectHandle1 (hchild
, childhProc
);
376 strace
.write_childpid (pi
.dwProcessId
);
378 /* Wait for subproc to initialize itself. */
379 if (!ch
.sync (pi
.dwProcessId
, hchild
, FORK_WAIT_TIMEOUT
))
381 if (!error ("forked process %u died unexpectedly, retry %d, exit code %y",
382 pi
.dwProcessId
, ch
.retry
, ch
.exit_code
))
390 /* Restore impersonation */
391 cygheap
->user
.reimpersonate ();
392 fix_impersonation
= false;
394 child_pid
= cygwin_pid (pi
.dwProcessId
);
395 child
.init (child_pid
, PID_IN_USE
| PID_NEW
, NULL
);
399 this_errno
= get_errno () == ENOMEM
? ENOMEM
: EAGAIN
;
400 syscall_printf ("pinfo failed");
404 child
->nice
= myself
->nice
;
406 /* Initialize things that are done later in dll_crt0_1 that aren't done
408 wcscpy (child
->progname
, myself
->progname
);
410 /* Fill in fields in the child's process table entry. */
411 child
->dwProcessId
= pi
.dwProcessId
;
412 child
.hProcess
= hchild
;
415 /* Hopefully, this will succeed. The alternative to doing things this
416 way is to reserve space prior to calling CreateProcess and then fill
417 it in afterwards. This requires more bookkeeping than I like, though,
418 so we'll just do it the easy way. So, terminate any child process if
419 we can't actually record the pid in the internal table. */
420 if (!child
.remember ())
424 error ("child remember failed");
429 /* CHILD IS STOPPED */
430 debug_printf ("child is alive (but stopped)");
433 /* Initialize, in order: stack, dll data, dll bss.
434 data, bss, heap were done earlier (in dcrt0.cc)
435 Note: variables marked as NO_COPY will not be copied since they are
436 placed in a protected segment. */
438 const void *impure_beg
;
439 const void *impure_end
;
441 if (&_my_tls
== _main_tls
)
442 impure_beg
= impure_end
= impure
= NULL
;
446 impure_beg
= _impure_ptr
;
447 impure_end
= _impure_ptr
+ 1;
449 rc
= child_copy (hchild
, true, !*with_forkables
,
450 "stack", stack_here
, ch
.stackbase
,
451 impure
, impure_beg
, impure_end
,
458 this_errno
= get_errno ();
459 error ("pid %u, exitval %p", pi
.dwProcessId
, ch
.exit_code
);
463 /* Now fill data/bss of any DLLs that were linked into the program. */
464 for (dll
*d
= dlls
.istart (DLL_LINK
); d
; d
= dlls
.inext ())
466 debug_printf ("copying data/bss of a linked dll");
467 if (!child_copy (hchild
, true, !*with_forkables
,
468 "linked dll data", d
->p
.data_start
, d
->p
.data_end
,
469 "linked dll bss", d
->p
.bss_start
, d
->p
.bss_end
,
472 this_errno
= get_errno ();
473 error ("couldn't copy linked dll data/bss");
478 /* Start the child up, and then wait for it to
479 perform fork fixups and dynamic dll loading (if any). */
480 resume_child (forker_finished
);
481 if (!ch
.sync (child
->pid
, hchild
, FORK_WAIT_TIMEOUT
))
484 error ("died waiting for dll loading");
488 /* If DLLs were loaded in the parent, then the child has reloaded all
489 of them and is now waiting to have all of the individual data and
490 bss sections filled in. */
493 /* CHILD IS STOPPED */
494 /* write memory of reloaded dlls */
495 for (dll
*d
= dlls
.istart (DLL_LOAD
); d
; d
= dlls
.inext ())
497 debug_printf ("copying data/bss for a loaded dll");
498 if (!child_copy (hchild
, true, !*with_forkables
,
499 "loaded dll data", d
->p
.data_start
, d
->p
.data_end
,
500 "loaded dll bss", d
->p
.bss_start
, d
->p
.bss_end
,
503 this_errno
= get_errno ();
505 error ("copying data/bss for a loaded dll");
512 /* Do not attach to the child before it has successfully initialized.
513 Otherwise we may wait forever, or deliver an orphan SIGCHILD. */
514 if (!child
.attach ())
518 error ("child attach failed");
523 /* Finally start the child up. */
524 resume_child (forker_finished
);
526 ForceCloseHandle (forker_finished
);
527 forker_finished
= NULL
;
531 /* Common cleanup code for failure cases */
533 /* release procinfo before hProcess in destructor */
534 child
.allow_remove ();
536 if (fix_impersonation
)
537 cygheap
->user
.reimpersonate ();
541 /* Remember to de-allocate the fd table. */
544 TerminateProcess (hchild
, 1);
545 if (!child
.hProcess
) /* no child.procinfo */
546 ForceCloseHandle1 (hchild
, childhProc
);
549 ForceCloseHandle (forker_finished
);
550 debug_printf ("returning -1");
557 bool with_forkables
= false; /* do not force hardlinks on first try */
558 int res
= dofork (NULL
, &with_forkables
);
562 return res
; /* no need for second try when already enabled */
563 with_forkables
= true; /* enable hardlinks for second try */
564 return dofork (NULL
, &with_forkables
);
568 /* __posix_spawn_fork is called from newlib's posix_spawn implementation.
569 The original code in newlib has been taken from FreeBSD, and the core
570 code relies on specific, non-portable behaviour of vfork(2). Our
571 replacement implementation needs the forked child's HANDLE for
572 synchronization, so __posix_spawn_fork returns it in proc. */
574 __posix_spawn_fork (void **proc
)
576 bool with_forkables
= false; /* do not force hardlinks on first try */
577 int res
= dofork (proc
, &with_forkables
);
581 return res
; /* no need for second try when already enabled */
582 with_forkables
= true; /* enable hardlinks for second try */
583 return dofork (proc
, &with_forkables
);
587 dofork (void **proc
, bool *with_forkables
)
589 frok
grouped (with_forkables
);
591 debug_printf ("entering");
592 grouped
.load_dlls
= 0;
595 bool ischild
= false;
597 myself
->set_has_pgid_children ();
599 if (grouped
.ch
.parent
== NULL
)
601 if (grouped
.ch
.subproc_ready
== NULL
)
603 system_printf ("unable to allocate subproc_ready event, %E");
608 hold_everything
held_everything (ischild
);
609 /* This tmp_pathbuf constructor is required here because the below setjmp
610 magic will otherwise not restore the original buffer count values in
611 the thread-local storage. A process forking too deeply will run into
612 the problem to be out of temporary TLS path buffers. */
615 if (!held_everything
)
623 /* Put the dll list in topological dependency ordering, in
624 hopes that the child will have a better shot at loading dlls
625 properly if it only has to deal with one at a time. */
628 ischild
= !!setjmp (grouped
.ch
.jmp
);
630 volatile char * volatile stackp
;
632 __asm__
volatile ("movq %%rsp,%0": "=r" (stackp
));
634 #error unimplemented for this target
638 res
= grouped
.parent (stackp
);
641 res
= grouped
.child (stackp
);
642 __in_forkee
= FORKED
;
643 ischild
= true; /* might have been reset by fork mem copy */
649 myself
->process_state
|= PID_ACTIVE
;
650 myself
->process_state
&= ~(PID_INITIALIZING
| PID_EXITED
| PID_REAPED
);
655 syscall_printf ("fork failed - child pid %d, errno %d", grouped
.child_pid
, grouped
.this_errno
);
656 else if (grouped
.ch
.silentfail ())
657 debug_printf ("child %d - %s, errno %d", grouped
.child_pid
,
658 grouped
.errmsg
, grouped
.this_errno
);
660 system_printf ("child %d - %s, errno %d", grouped
.child_pid
,
661 grouped
.errmsg
, grouped
.this_errno
);
663 set_errno (grouped
.this_errno
);
667 /* Return child process handle to posix_fork. */
668 *proc
= grouped
.hchild
;
670 syscall_printf ("%R = fork()", res
);
684 debug_printf ("stub called");
688 /* Copy memory from one process to another. */
691 child_copy (HANDLE hp
, bool write
, bool silentfail
, ...)
694 va_start (args
, silentfail
);
695 static const char *huh
[] = {"read", "write"};
698 while ((what
= va_arg (args
, char *)))
700 char *low
= va_arg (args
, char *);
701 char *high
= va_arg (args
, char *);
702 SIZE_T todo
= high
- low
;
705 for (here
= low
; here
< high
; here
+= todo
)
708 if (here
+ todo
> high
)
712 res
= WriteProcessMemory (hp
, here
, here
, todo
, &done
);
714 res
= ReadProcessMemory (hp
, here
, here
, todo
, &done
);
715 debug_printf ("%s - hp %p low %p, high %p, res %d", what
, hp
, low
, high
, res
);
716 if (!res
|| todo
!= done
)
721 debug_printf ("%s %s copy failed, %p..%p, done %lu, windows pid %u, %E",
722 what
, huh
[write
], low
, high
, done
, myself
->dwProcessId
);
724 /* If this happens then there is a bug in our fork
725 implementation somewhere. */
726 system_printf ("%s %s copy failed, %p..%p, done %lu, windows pid %u, %E",
727 what
, huh
[write
], low
, high
, done
, myself
->dwProcessId
);
734 debug_printf ("done");
739 TerminateProcess (hp
, 1);