]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/fork.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / cygwin / fork.cc
CommitLineData
1fd5e000
CF
1/* fork.cc
2
bc837d22 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
3c53eaeb 4 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
1fd5e000
CF
5
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
4c8d72de 12#include "winsup.h"
1fd5e000
CF
13#include <stdio.h>
14#include <unistd.h>
15#include <stdlib.h>
169c465a 16#include "cygerrno.h"
0e1f0840
CF
17#include "sigproc.h"
18#include "pinfo.h"
47063f00 19#include "path.h"
7ac61736 20#include "fhandler.h"
e2ebe117 21#include "dtable.h"
b0e82b74 22#include "cygheap.h"
488c7683 23#include "child_info.h"
8cb359d9 24#include "cygtls.h"
752b16ce 25#include "tls_pbuf.h"
f0338f54 26#include "dll_init.h"
c7e2187a 27#include "cygmalloc.h"
89d3c72d 28#include "ntdll.h"
1fd5e000 29
22cf17b3 30#define NPIDS_HELD 4
a9f36d28 31
1fd5e000
CF
32/* Timeout to wait for child to start, parent to init child, etc. */
33/* FIXME: Once things stabilize, bump up to a few minutes. */
34#define FORK_WAIT_TIMEOUT (300 * 1000) /* 300 seconds */
35
280fdd0b
CF
36class frok
37{
280fdd0b
CF
38 bool load_dlls;
39 child_info_fork ch;
85510878 40 const char *errmsg;
280fdd0b
CF
41 int child_pid;
42 int this_errno;
85510878 43 HANDLE hchild;
39fc0d36
CF
44 int __stdcall parent (volatile char * volatile here);
45 int __stdcall child (volatile char * volatile here);
85510878 46 bool error (const char *fmt, ...);
280fdd0b
CF
47 friend int fork ();
48};
49
bbca1e4c 50static void
54dd79bb 51resume_child (HANDLE forker_finished)
1fd5e000 52{
1fd5e000 53 SetEvent (forker_finished);
1ec4f618 54 debug_printf ("signalled child");
bbca1e4c 55 return;
1fd5e000
CF
56}
57
3178cfff 58/* Notify parent that it is time for the next step. */
1ec4f618 59static void __stdcall
c90e1cf1 60sync_with_parent (const char *s, bool hang_self)
1fd5e000 61{
1ec4f618 62 debug_printf ("signalling parent: %s", s);
54dd79bb 63 fork_info->ready (false);
1ec4f618
CF
64 if (hang_self)
65 {
6ea3e429 66 HANDLE h = fork_info->forker_finished;
1ec4f618
CF
67 /* Wait for the parent to fill in our stack and heap.
68 Don't wait forever here. If our parent dies we don't want to clog
69 the system. If the wait fails, we really can't continue so exit. */
70 DWORD psync_rc = WaitForSingleObject (h, FORK_WAIT_TIMEOUT);
71 debug_printf ("awake");
72 switch (psync_rc)
73 {
74 case WAIT_TIMEOUT:
e431827c 75 api_fatal ("WFSO timed out %s", s);
1ec4f618
CF
76 break;
77 case WAIT_FAILED:
78 if (GetLastError () == ERROR_INVALID_HANDLE &&
6ea3e429 79 WaitForSingleObject (fork_info->forker_finished, 1) != WAIT_FAILED)
1ec4f618 80 break;
e431827c 81 api_fatal ("WFSO failed %s, fork_finished %p, %E", s,
6ea3e429 82 fork_info->forker_finished);
1ec4f618
CF
83 break;
84 default:
85 debug_printf ("no problems");
86 break;
87 }
88 }
1fd5e000
CF
89}
90
85510878
CF
91bool
92frok::error (const char *fmt, ...)
93{
94 DWORD exit_code = ch.exit_code;
95 if (!exit_code && hchild)
96 {
97 exit_code = ch.proc_retry (hchild);
98 if (!exit_code)
99 return false;
100 }
101 if (exit_code != EXITCODE_FORK_FAILED)
102 {
103 va_list ap;
104 static char buf[NT_MAX_PATH + 256];
105 va_start (ap, fmt);
106 __small_vsprintf (buf, fmt, ap);
107 errmsg = buf;
108 }
109 return true;
110}
111
1fb6667f
CF
112/* Set up a pipe which will track the life of a "pid" through
113 even after we've exec'ed. */
114void
115child_info::prefork (bool detached)
116{
117 if (!detached)
118 {
119 if (!CreatePipe (&rd_proc_pipe, &wr_proc_pipe, &sec_none_nih, 16))
81f18683 120 api_fatal ("prefork: couldn't create pipe process tracker, %E");
1fb6667f
CF
121
122 if (!SetHandleInformation (wr_proc_pipe, HANDLE_FLAG_INHERIT,
123 HANDLE_FLAG_INHERIT))
124 api_fatal ("prefork: couldn't set process pipe(%p) inherit state, %E",
125 wr_proc_pipe);
126 ProtectHandle1 (rd_proc_pipe, rd_proc_pipe);
127 ProtectHandle1 (wr_proc_pipe, wr_proc_pipe);
128 }
129}
130
280fdd0b 131int __stdcall
39fc0d36 132frok::child (volatile char * volatile here)
1fd5e000 133{
280fdd0b 134 HANDLE& hParent = ch.parent;
b1d9a0bd 135 extern void fixup_hooks_after_fork ();
f6936c48 136 extern void fixup_timers_after_fork ();
1ec4f618 137
6642f7da
CF
138 /* NOTE: Logically this belongs in dll_list::load_after_fork, but by
139 doing it here, before the first sync_with_parent, we can exploit
140 the existing retry mechanism in hopes of getting a more favorable
141 address space layout next time. */
142 dlls.reserve_space ();
143
2e008fb9 144 sync_with_parent ("after longjmp", true);
ef8bff85
CF
145 debug_printf ("child is running. pid %d, ppid %d, stack here %p",
146 myself->pid, myself->ppid, __builtin_frame_address (0));
71f53a2f 147 sigproc_printf ("hParent %p, load_dlls %d", hParent, load_dlls);
1fd5e000 148
e431827c
CF
149 /* If we've played with the stack, stacksize != 0. That means that
150 fork() was invoked from other than the main thread. Make sure that
151 the threadinfo information is properly set up. */
89d3c72d 152 if (fork_info->stackaddr)
e431827c
CF
153 {
154 _main_tls = &_my_tls;
155 _main_tls->init_thread (NULL, NULL);
156 _main_tls->local_clib = *_impure_ptr;
157 _impure_ptr = &_main_tls->local_clib;
158 }
159
a76877e9
CV
160 set_cygwin_privileges (hProcToken);
161 clear_procimptoken ();
162 cygheap->user.reimpersonate ();
f4a1f8a1 163
1ec4f618 164#ifdef DEBUGGING
5ab0b5cf 165 if (GetEnvironmentVariableA ("FORKDEBUG", NULL, 0))
1ec4f618
CF
166 try_to_debug ();
167 char buf[80];
168 /* This is useful for debugging fork problems. Use gdb to attach to
169 the pid reported here. */
5ab0b5cf 170 if (GetEnvironmentVariableA ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
1ec4f618
CF
171 {
172 small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
c90e1cf1 173 Sleep (atoi (buf));
1ec4f618
CF
174 }
175#endif
1fd5e000 176
1ec4f618 177 MALLOC_CHECK;
1fd5e000 178
b6e69d53
CV
179 /* Incredible but true: If we use sockets and SYSV IPC shared memory,
180 there's a good chance that a duplicated socket in the child occupies
181 memory which is needed to duplicate shared memory from the parent
182 process, if the shared memory hasn't been duplicated already.
183 The same goes very likely for "normal" mmap shared memory, too, but
184 with SYSV IPC it was the first time observed. So, *never* fixup
185 fdtab before fixing up shared memory. */
186 if (fixup_shms_after_fork ())
187 api_fatal ("recreate_shm areas after fork failed");
5ec14fe4 188
1ec4f618
CF
189 MALLOC_CHECK;
190
191 /* If we haven't dynamically loaded any dlls, just signal
192 the parent. Otherwise, load all the dlls, tell the parent
193 that we're done, and wait for the parent to fill in the.
194 loaded dlls' data/bss. */
195 if (!load_dlls)
d525130f
CF
196 {
197 cygheap->fdtab.fixup_after_fork (hParent);
2e008fb9 198 sync_with_parent ("performed fork fixup", false);
d525130f 199 }
1ec4f618 200 else
1fd5e000 201 {
71f53a2f 202 dlls.load_after_fork (hParent);
d525130f 203 cygheap->fdtab.fixup_after_fork (hParent);
2e008fb9 204 sync_with_parent ("loaded dlls", true);
1fd5e000
CF
205 }
206
44d2fc0a 207 init_console_handler (myself->ctty > 0);
0c55f6ed 208 ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
2eb392bd 209
f1f13795 210 pthread::atforkchild ();
f6936c48 211 fixup_timers_after_fork ();
166b2571 212 cygbench ("fork-child");
b21413b3 213 ld_preload ();
f02b22dc 214 fixup_hooks_after_fork ();
f02b22dc 215 _my_tls.fixup_after_fork ();
1fb6667f
CF
216 /* Clear this or the destructor will close them. In the case of
217 rd_proc_pipe that would be an invalid handle. In the case of
218 wr_proc_pipe it would be == my_wr_proc_pipe. Both would be bad. */
219 ch.rd_proc_pipe = ch.wr_proc_pipe = NULL;
f359a29f 220 cygwin_finished_initializing = true;
1ec4f618
CF
221 return 0;
222}
1fd5e000 223
280fdd0b 224#define NO_SLOW_PID_REUSE
5d9a7c87 225#ifndef NO_SLOW_PID_REUSE
84aeff41
CF
226static void
227slow_pid_reuse (HANDLE h)
228{
24515d65
CF
229 static NO_COPY HANDLE last_fork_procs[NPIDS_HELD];
230 static NO_COPY unsigned nfork_procs;
84aeff41 231
5ba05cab 232 if (nfork_procs >= (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
84aeff41 233 nfork_procs = 0;
54dd79bb 234 /* Keep a list of handles to child processes sitting around to prevent
84aeff41
CF
235 Windows from reusing the same pid n times in a row. Having the same pids
236 close in succesion confuses bash. Keeping a handle open will stop
237 windows from reusing the same pid. */
238 if (last_fork_procs[nfork_procs])
5ba05cab 239 ForceCloseHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
f16706de
CV
240 if (DuplicateHandle (GetCurrentProcess (), h,
241 GetCurrentProcess (), &last_fork_procs[nfork_procs],
242 0, FALSE, DUPLICATE_SAME_ACCESS))
5ba05cab
CF
243 ProtectHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
244 else
84aeff41
CF
245 {
246 last_fork_procs[nfork_procs] = NULL;
247 system_printf ("couldn't create last_fork_proc, %E");
248 }
249 nfork_procs++;
250}
89e7a1ce 251#endif
84aeff41 252
280fdd0b 253int __stdcall
39fc0d36 254frok::parent (volatile char * volatile stack_here)
1ec4f618 255{
54dd79bb 256 HANDLE forker_finished;
1ec4f618 257 DWORD rc;
280fdd0b 258 child_pid = -1;
280fdd0b
CF
259 this_errno = 0;
260 bool fix_impersonation = false;
261 pinfo child;
1fd5e000 262
f16706de 263 int c_flags = GetPriorityClass (GetCurrentProcess ());
0dc24975 264 debug_printf ("priority class %d", c_flags);
1ec4f618 265
85510878
CF
266 errmsg = NULL;
267 hchild = NULL;
268
1ec4f618
CF
269 /* If we don't have a console, then don't create a console for the
270 child either. */
580e99a1 271 HANDLE console_handle = CreateFile ("CONOUT$", GENERIC_WRITE,
fc3e7da6
CV
272 FILE_SHARE_READ | FILE_SHARE_WRITE,
273 &sec_none_nih, OPEN_EXISTING,
274 FILE_ATTRIBUTE_NORMAL, NULL);
1ec4f618 275
580e99a1 276 if (console_handle != INVALID_HANDLE_VALUE)
1ec4f618
CF
277 CloseHandle (console_handle);
278 else
279 c_flags |= DETACHED_PROCESS;
1fd5e000 280
b14f53a8
CV
281 /* Some file types (currently only sockets) need extra effort in the
282 parent after CreateProcess and before copying the datastructures
283 to the child. So we have to start the child in suspend state,
284 unfortunately, to avoid a race condition. */
285 if (cygheap->fdtab.need_fixup_before ())
286 c_flags |= CREATE_SUSPENDED;
287
71f53a2f
CF
288 /* Remember if we need to load dynamically linked dlls.
289 We do this here so that this information will be available
290 in the parent and, when the stack is copied, in the child. */
1ec4f618 291 load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
1fd5e000 292
1ec4f618
CF
293 forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
294 if (forker_finished == NULL)
295 {
280fdd0b 296 this_errno = geterrno_from_win_error ();
85510878 297 error ("unable to allocate forker_finished event");
1ec4f618
CF
298 return -1;
299 }
1fd5e000 300
0301bfd0 301 ProtectHandleINH (forker_finished);
1fd5e000 302
1ec4f618 303 ch.forker_finished = forker_finished;
1fd5e000 304
0dc24975 305 ch.stackbottom = _tlsbase;
89d3c72d
CV
306 ch.stacktop = (void *) _tlstop;
307 ch.stackaddr = 0;
308 ch.guardsize = 0;
309 if (&_my_tls != _main_tls)
310 {
311 /* We have not been started from the main thread. Fetch the
312 information required to set up the thread stack identically
313 in the child. */
314 PTEB teb = NtCurrentTeb ();
315 if (!teb->DeallocationStack)
b86f999a 316 {
89d3c72d
CV
317 /* Pthread with application-provided stack. Don't set up a
318 PAGE_GUARD page. guardsize == -1 is used in alloc_stack_hard_way
319 to recognize this type of stack. */
320 ch.stackaddr = _my_tls.tid->attr.stackaddr;
321 ch.guardsize = (size_t) -1;
322 }
323 else
324 {
325 ch.stackaddr = teb->DeallocationStack;
326 /* If it's a pthread, fetch guardsize from thread attributes. */
327 if (_my_tls.tid)
328 ch.guardsize = _my_tls.tid->attr.guardsize;
329 }
330 }
61522196 331 debug_printf ("stack - bottom %p, top %p, addr %p, guardsize %lu",
89d3c72d 332 ch.stackbottom, ch.stacktop, ch.stackaddr, ch.guardsize);
1fd5e000 333
bbca1e4c 334 PROCESS_INFORMATION pi;
752b16ce 335 STARTUPINFOW si;
bbca1e4c
CF
336
337 memset (&si, 0, sizeof (si));
752b16ce 338 si.cb = sizeof si;
c6674b53 339
54dd79bb 340 si.lpReserved2 = (LPBYTE) &ch;
c90e1cf1 341 si.cbReserved2 = sizeof (ch);
1fd5e000 342
61522196 343 syscall_printf ("CreateProcessW (%W, %W, 0, 0, 1, %y, 0, 0, %p, %p)",
d3258e06 344 myself->progname, myself->progname, c_flags, &si, &pi);
12b33712
CF
345 bool locked = __malloc_lock ();
346 time_t start_time = time (NULL);
347
1ec4f618 348 /* Remove impersonation */
70249d56 349 cygheap->user.deimpersonate ();
280fdd0b 350 fix_impersonation = true;
977ad543 351 ch.refresh_cygheap ();
1fb6667f 352 ch.prefork (); /* set up process tracking pipes. */
1fd5e000 353
84d38174 354 while (1)
1ec4f618 355 {
85510878 356 hchild = NULL;
30fa1549
CF
357 rc = CreateProcessW (myself->progname, /* image to run */
358 myself->progname, /* what we send in arg0 */
752b16ce
CV
359 &sec_none_nih,
360 &sec_none_nih,
30fa1549 361 TRUE, /* inherit handles from parent */
752b16ce 362 c_flags,
30fa1549
CF
363 NULL, /* environment filled in later */
364 0, /* use current drive/directory */
752b16ce
CV
365 &si,
366 &pi);
84d38174 367
56a19715
CF
368 if (rc)
369 debug_printf ("forked pid %u", pi.dwProcessId);
370 else
84d38174
CF
371 {
372 this_errno = geterrno_from_win_error ();
85510878 373 error ("CreateProcessW failed for '%W'", myself->progname);
84d38174
CF
374 memset (&pi, 0, sizeof (pi));
375 goto cleanup;
376 }
64b30629 377
b14f53a8
CV
378 if (cygheap->fdtab.need_fixup_before ())
379 {
380 cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
381 ResumeThread (pi.hThread);
382 }
383
a9396868 384 CloseHandle (pi.hThread);
85510878 385 hchild = pi.hProcess;
a9396868
CF
386
387 /* Protect the handle but name it similarly to the way it will
388 be called in subproc handling. */
85510878 389 ProtectHandle1 (hchild, childhProc);
a9396868 390
ef8bff85 391 strace.write_childpid (pi.dwProcessId);
84d38174
CF
392
393 /* Wait for subproc to initialize itself. */
85510878 394 if (!ch.sync (pi.dwProcessId, hchild, FORK_WAIT_TIMEOUT))
84d38174 395 {
dfd5d5be
CF
396 if (!error ("forked process %u died unexpectedly, retry %d, exit code %d",
397 pi.dwProcessId, ch.retry, ch.exit_code))
f02400f7 398 continue;
84d38174 399 this_errno = EAGAIN;
84d38174
CF
400 goto cleanup;
401 }
402 break;
403 }
5d970405 404
12b33712
CF
405 /* Restore impersonation */
406 cygheap->user.reimpersonate ();
407 fix_impersonation = false;
408
280fdd0b
CF
409 child_pid = cygwin_pid (pi.dwProcessId);
410 child.init (child_pid, 1, NULL);
72067cca 411
54dd79bb 412 if (!child)
6c68fbbc 413 {
280fdd0b 414 this_errno = get_errno () == ENOMEM ? ENOMEM : EAGAIN;
6c68fbbc 415 syscall_printf ("pinfo failed");
6c68fbbc
CF
416 goto cleanup;
417 }
1fd5e000 418
84d38174 419 child->start_time = start_time; /* Register child's starting time. */
f834829d
CF
420 child->nice = myself->nice;
421
1ec4f618
CF
422 /* Initialize things that are done later in dll_crt0_1 that aren't done
423 for the forkee. */
d3258e06 424 wcscpy (child->progname, myself->progname);
1fd5e000 425
1ec4f618 426 /* Fill in fields in the child's process table entry. */
54dd79bb 427 child->dwProcessId = pi.dwProcessId;
85510878 428 child.hProcess = hchild;
b7d95b5b 429 ch.postfork (child);
cde0c2fb
CF
430
431 /* Hopefully, this will succeed. The alternative to doing things this
432 way is to reserve space prior to calling CreateProcess and then fill
433 it in afterwards. This requires more bookkeeping than I like, though,
434 so we'll just do it the easy way. So, terminate any child process if
435 we can't actually record the pid in the internal table. */
4ee52924 436 if (!child.remember (false))
cde0c2fb 437 {
85510878 438 TerminateProcess (hchild, 1);
280fdd0b 439 this_errno = EAGAIN;
40c7d132 440#ifdef DEBUGGING0
85510878 441 error ("child remember failed");
280fdd0b 442#endif
cde0c2fb
CF
443 goto cleanup;
444 }
445
5d9a7c87 446#ifndef NO_SLOW_PID_REUSE
85510878 447 slow_pid_reuse (hchild);
89e7a1ce 448#endif
1ec4f618 449
1ec4f618
CF
450 /* CHILD IS STOPPED */
451 debug_printf ("child is alive (but stopped)");
452
ef8bff85 453
12b33712
CF
454 /* Initialize, in order: stack, dll data, dll bss.
455 data, bss, heap were done earlier (in dcrt0.cc)
456 Note: variables marked as NO_COPY will not be copied since they are
457 placed in a protected segment. */
1fd5e000 458
1ec4f618 459 MALLOC_CHECK;
ad02bb70
CF
460 const void *impure_beg;
461 const void *impure_end;
462 const char *impure;
29d52c8a 463 if (&_my_tls == _main_tls)
ad02bb70 464 impure_beg = impure_end = impure = NULL;
29d52c8a
CF
465 else
466 {
ad02bb70 467 impure = "impure";
29d52c8a
CF
468 impure_beg = _impure_ptr;
469 impure_end = _impure_ptr + 1;
470 }
85510878 471 rc = child_copy (hchild, true,
ad02bb70
CF
472 "stack", stack_here, ch.stackbottom,
473 impure, impure_beg, impure_end,
474 NULL);
1fd5e000 475
c7e2187a 476 __malloc_unlock ();
e431827c 477 locked = false;
1ec4f618
CF
478 MALLOC_CHECK;
479 if (!rc)
bbca1e4c
CF
480 {
481 this_errno = get_errno ();
85510878 482 error ("pid %u, exitval %p", pi.dwProcessId, ch.exit_code);
bbca1e4c
CF
483 goto cleanup;
484 }
1fd5e000 485
1ec4f618
CF
486 /* Now fill data/bss of any DLLs that were linked into the program. */
487 for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
488 {
489 debug_printf ("copying data/bss of a linked dll");
85510878 490 if (!child_copy (hchild, true,
ad02bb70
CF
491 "linked dll data", d->p.data_start, d->p.data_end,
492 "linked dll bss", d->p.bss_start, d->p.bss_end,
493 NULL))
280fdd0b
CF
494 {
495 this_errno = get_errno ();
85510878 496 error ("couldn't copy linked dll data/bss");
280fdd0b
CF
497 goto cleanup;
498 }
1fd5e000 499 }
1fd5e000 500
bbca1e4c
CF
501 /* Start thread, and then wait for it to reload dlls. */
502 resume_child (forker_finished);
85510878 503 if (!ch.sync (child->pid, hchild, FORK_WAIT_TIMEOUT))
54dd79bb 504 {
280fdd0b 505 this_errno = EAGAIN;
85510878 506 error ("died waiting for dll loading");
54dd79bb
CF
507 goto cleanup;
508 }
1fd5e000 509
1ec4f618
CF
510 /* If DLLs were loaded in the parent, then the child has reloaded all
511 of them and is now waiting to have all of the individual data and
512 bss sections filled in. */
513 if (load_dlls)
514 {
515 /* CHILD IS STOPPED */
516 /* write memory of reloaded dlls */
517 for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
1fd5e000 518 {
1ec4f618 519 debug_printf ("copying data/bss for a loaded dll");
85510878 520 if (!child_copy (hchild, true,
ad02bb70
CF
521 "loaded dll data", d->p.data_start, d->p.data_end,
522 "loaded dll bss", d->p.bss_start, d->p.bss_end,
523 NULL))
280fdd0b
CF
524 {
525 this_errno = get_errno ();
526#ifdef DEBUGGING
85510878 527 error ("copying data/bss for a loaded dll");
280fdd0b
CF
528#endif
529 goto cleanup;
530 }
1fd5e000 531 }
1ec4f618 532 /* Start the child up again. */
0c55f6ed 533 resume_child (forker_finished);
1fd5e000
CF
534 }
535
1ec4f618
CF
536 ForceCloseHandle (forker_finished);
537 forker_finished = NULL;
1fd5e000 538
54dd79bb 539 return child_pid;
1fd5e000
CF
540
541/* Common cleanup code for failure cases */
280fdd0b
CF
542cleanup:
543 if (fix_impersonation)
544 cygheap->user.reimpersonate ();
e431827c
CF
545 if (locked)
546 __malloc_unlock ();
547
1fd5e000 548 /* Remember to de-allocate the fd table. */
85510878
CF
549 if (hchild && !child.hProcess)
550 ForceCloseHandle1 (hchild, childhProc);
1fd5e000
CF
551 if (forker_finished)
552 ForceCloseHandle (forker_finished);
280fdd0b 553 debug_printf ("returning -1");
1fd5e000
CF
554 return -1;
555}
556
1ec4f618
CF
557extern "C" int
558fork ()
1fd5e000 559{
280fdd0b 560 frok grouped;
1ec4f618 561
1ec4f618 562 debug_printf ("entering");
aece55b9 563 grouped.load_dlls = 0;
1ec4f618 564
f02b22dc 565 int res;
39fc0d36 566 bool ischild = false;
f02b22dc 567
f8f9b12e
CF
568 myself->set_has_pgid_children ();
569
ce95c640
CF
570 if (grouped.ch.parent == NULL)
571 return -1;
572 if (grouped.ch.subproc_ready == NULL)
54dd79bb
CF
573 {
574 system_printf ("unable to allocate subproc_ready event, %E");
575 return -1;
576 }
1ec4f618 577
39fc0d36
CF
578 {
579 hold_everything held_everything (ischild);
637a1aec
CV
580 /* This tmp_pathbuf constructor is required here because the below setjmp
581 magic will otherwise not restore the original buffer count values in
582 the thread-local storage. A process forking too deeply will run into
583 the problem to be out of temporary TLS path buffers. */
584 tmp_pathbuf tp;
07f89f85 585
39fc0d36
CF
586 if (!held_everything)
587 {
588 if (exit_state)
589 Sleep (INFINITE);
590 set_errno (EAGAIN);
591 return -1;
592 }
7912bcbf 593
977ad543
CF
594 /* Put the dll list in topological dependency ordering, in
595 hopes that the child will have a better shot at loading dlls
596 properly if it only has to deal with one at a time. */
597 dlls.topsort ();
598
39fc0d36 599 ischild = !!setjmp (grouped.ch.jmp);
7912bcbf 600
61522196
CV
601 volatile char * volatile stackp;
602#ifdef __x86_64__
603 __asm__ volatile ("movq %%rsp,%0": "=r" (stackp));
604#else
605 __asm__ volatile ("movl %%esp,%0": "=r" (stackp));
606#endif
39fc0d36 607
39fc0d36 608 if (!ischild)
61522196 609 res = grouped.parent (stackp);
39fc0d36 610 else
e943a1a3 611 {
61522196 612 res = grouped.child (stackp);
85510878 613 in_forkee = false;
e943a1a3
CF
614 ischild = true; /* might have been reset by fork mem copy */
615 }
39fc0d36 616 }
1ec4f618
CF
617
618 MALLOC_CHECK;
b9874a0c 619 if (ischild)
fc0e5071
CF
620 {
621 myself->process_state |= PID_ACTIVE;
b8424c5e 622 myself->process_state &= ~(PID_INITIALIZING | PID_EXITED | PID_REAPED);
fc0e5071 623 }
b9874a0c 624 else if (res < 0)
280fdd0b 625 {
85510878 626 if (!grouped.errmsg)
40c7d132 627 syscall_printf ("fork failed - child pid %d, errno %d", grouped.child_pid, grouped.this_errno);
280fdd0b 628 else
40c7d132 629 {
85510878 630 char buf[strlen (grouped.errmsg) + sizeof ("child %d - , errno 4294967295 ")];
40c7d132 631 strcpy (buf, "child %d - ");
85510878 632 strcat (buf, grouped.errmsg);
40c7d132
CF
633 strcat (buf, ", errno %d");
634 system_printf (buf, grouped.child_pid, grouped.this_errno);
635 }
636
280fdd0b
CF
637 set_errno (grouped.this_errno);
638 }
b9aa8149 639 syscall_printf ("%R = fork()", res);
1ec4f618 640 return res;
1fd5e000 641}
84aeff41
CF
642#ifdef DEBUGGING
643void
644fork_init ()
645{
84aeff41
CF
646}
647#endif /*DEBUGGING*/
1fd5e000 648
1fd5e000 649
8dca9e23 650extern "C" int
1fd5e000
CF
651vfork ()
652{
9e1ad59d 653 debug_printf ("stub called");
1fd5e000 654 return fork ();
1fd5e000 655}
ce95c640 656
ad02bb70
CF
657/* Copy memory from one process to another. */
658
659bool
660child_copy (HANDLE hp, bool write, ...)
ce95c640 661{
ad02bb70
CF
662 va_list args;
663 va_start (args, write);
664 static const char *huh[] = {"read", "write"};
665
666 char *what;
667 while ((what = va_arg (args, char *)))
668 {
669 char *low = va_arg (args, char *);
670 char *high = va_arg (args, char *);
61522196 671 SIZE_T todo = high - low;
ad02bb70
CF
672 char *here;
673
674 for (here = low; here < high; here += todo)
675 {
61522196 676 SIZE_T done = 0;
ad02bb70
CF
677 if (here + todo > high)
678 todo = high - here;
679 int res;
680 if (write)
681 res = WriteProcessMemory (hp, here, here, todo, &done);
682 else
683 res = ReadProcessMemory (hp, here, here, todo, &done);
5d970405 684 debug_printf ("%s - hp %p low %p, high %p, res %d", what, hp, low, high, res);
ad02bb70
CF
685 if (!res || todo != done)
686 {
687 if (!res)
688 __seterrno ();
689 /* If this happens then there is a bug in our fork
690 implementation somewhere. */
61522196 691 system_printf ("%s %s copy failed, %p..%p, done %lu, windows pid %u, %E",
0b7c56a5 692 what, huh[write], low, high, done, myself->dwProcessId);
ad02bb70
CF
693 goto err;
694 }
695 }
696 }
697
4cd31fc8 698 va_end (args);
ad02bb70
CF
699 debug_printf ("done");
700 return true;
701
702 err:
4cd31fc8 703 va_end (args);
ad02bb70
CF
704 TerminateProcess (hp, 1);
705 set_errno (EAGAIN);
706 return false;
ce95c640 707}
This page took 0.51163 seconds and 5 git commands to generate.