OSDN Git Service

* child_info.h (child_info::cygheap_h): Delete.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / fork.cc
1 /* fork.cc
2
3    Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005
4    Red Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 #include "winsup.h"
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include "cygerrno.h"
18 #include "security.h"
19 #include "path.h"
20 #include "fhandler.h"
21 #include "dtable.h"
22 #include "sigproc.h"
23 #include "pinfo.h"
24 #include "cygheap.h"
25 #include "child_info.h"
26 #include "cygtls.h"
27 #include "perprocess.h"
28 #include "dll_init.h"
29 #include "sync.h"
30 #include "shared_info.h"
31 #include "cygmalloc.h"
32 #include "cygthread.h"
33
34 #define NPIDS_HELD 4
35
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 */
39
40 #define dll_data_start &_data_start__
41 #define dll_data_end &_data_end__
42 #define dll_bss_start &_bss_start__
43 #define dll_bss_end &_bss_end__
44
45 static void
46 stack_base (child_info_fork &ch)
47 {
48   MEMORY_BASIC_INFORMATION m;
49   memset (&m, 0, sizeof m);
50   if (!VirtualQuery ((LPCVOID) &m, &m, sizeof m))
51     system_printf ("couldn't get memory info, %E");
52
53   ch.stacktop = m.AllocationBase;
54   ch.stackbottom = (LPBYTE) m.BaseAddress + m.RegionSize;
55   ch.stacksize = (DWORD) ch.stackbottom - (DWORD) &m;
56   debug_printf ("bottom %p, top %p, stack %p, size %d, reserve %d",
57                 ch.stackbottom, ch.stacktop, &m, ch.stacksize,
58                 (DWORD) ch.stackbottom - (DWORD) ch.stacktop);
59 }
60
61 /* Copy memory from parent to child.
62    The result is a boolean indicating success.  */
63
64 static int
65 fork_copy (PROCESS_INFORMATION &pi, const char *what, ...)
66 {
67   va_list args;
68   char *low;
69   int pass = 0;
70
71   va_start (args, what);
72
73   while ((low = va_arg (args, char *)))
74     {
75       char *high = va_arg (args, char *);
76       DWORD todo = wincap.chunksize () ?: high - low;
77       char *here;
78
79       for (here = low; here < high; here += todo)
80         {
81           DWORD done = 0;
82           if (here + todo > high)
83             todo = high - here;
84           int res;
85           if (pi.hThread)
86             res = WriteProcessMemory (pi.hProcess, here, here, todo, &done);
87           else
88             res = ReadProcessMemory (pi.hProcess, here, here, todo, &done);
89           debug_printf ("child handle %p, low %p, high %p, res %d", pi.hProcess,
90                         low, high, res);
91           if (!res || todo != done)
92             {
93               if (!res)
94                 __seterrno ();
95               /* If this happens then there is a bug in our fork
96                  implementation somewhere. */
97               system_printf ("%s pass %d failed, %p..%p, done %d, windows pid %u, %E",
98                             what, pass, low, high, done, pi.dwProcessId);
99               goto err;
100             }
101         }
102
103       pass++;
104     }
105
106   debug_printf ("done");
107   return 1;
108
109  err:
110   TerminateProcess (pi.hProcess, 1);
111   set_errno (EAGAIN);
112   return 0;
113 }
114
115 static int
116 resume_child (HANDLE forker_finished)
117 {
118   SetEvent (forker_finished);
119   debug_printf ("signalled child");
120   return 1;
121 }
122
123 /* Notify parent that it is time for the next step. */
124 static void __stdcall
125 sync_with_parent (const char *s, bool hang_self)
126 {
127   debug_printf ("signalling parent: %s", s);
128   fork_info->ready (false);
129   if (hang_self)
130     {
131       HANDLE h = fork_info->forker_finished;
132       /* Wait for the parent to fill in our stack and heap.
133          Don't wait forever here.  If our parent dies we don't want to clog
134          the system.  If the wait fails, we really can't continue so exit.  */
135       DWORD psync_rc = WaitForSingleObject (h, FORK_WAIT_TIMEOUT);
136       debug_printf ("awake");
137       switch (psync_rc)
138         {
139         case WAIT_TIMEOUT:
140           api_fatal ("WFSO timed out %s", s);
141           break;
142         case WAIT_FAILED:
143           if (GetLastError () == ERROR_INVALID_HANDLE &&
144               WaitForSingleObject (fork_info->forker_finished, 1) != WAIT_FAILED)
145             break;
146           api_fatal ("WFSO failed %s, fork_finished %p, %E", s,
147                      fork_info->forker_finished);
148           break;
149         default:
150           debug_printf ("no problems");
151           break;
152         }
153     }
154 }
155
156 static int __stdcall
157 fork_child (HANDLE& hParent, dll *&first_dll, bool& load_dlls)
158 {
159   extern void fixup_hooks_after_fork ();
160   extern void fixup_timers_after_fork ();
161   extern void __stdcall create_signal_arrived ();
162   debug_printf ("child is running.  pid %d, ppid %d, stack here %p",
163                 myself->pid, myself->ppid, __builtin_frame_address (0));
164
165   sync_with_parent ("after longjmp", true);
166   sigproc_printf ("hParent %p, child 1 first_dll %p, load_dlls %d", hParent,
167                   first_dll, load_dlls);
168
169   /* If we've played with the stack, stacksize != 0.  That means that
170      fork() was invoked from other than the main thread.  Make sure that
171      the threadinfo information is properly set up.  */
172   if (fork_info->stacksize)
173     {
174       _main_tls = &_my_tls;
175       _main_tls->init_thread (NULL, NULL);
176       _main_tls->local_clib = *_impure_ptr;
177       _impure_ptr = &_main_tls->local_clib;
178     }
179
180   if (wincap.has_security ())
181     {
182       set_cygwin_privileges (hProcImpToken);
183       cygheap->user.reimpersonate ();
184     }
185
186 #ifdef DEBUGGING
187   char c;
188   if (GetEnvironmentVariable ("FORKDEBUG", &c, 1))
189     try_to_debug ();
190   char buf[80];
191   /* This is useful for debugging fork problems.  Use gdb to attach to
192      the pid reported here. */
193   if (GetEnvironmentVariable ("CYGWIN_FORK_SLEEP", buf, sizeof (buf)))
194     {
195       small_printf ("Sleeping %d after fork, pid %u\n", atoi (buf), GetCurrentProcessId ());
196       Sleep (atoi (buf));
197     }
198 #endif
199
200   set_file_api_mode (current_codepage);
201
202   MALLOC_CHECK;
203
204   if (fixup_mmaps_after_fork (hParent))
205     api_fatal ("recreate_mmaps_after_fork_failed");
206
207   create_signal_arrived ();
208
209 #ifdef USE_SERVER
210   /* Incredible but true:  If we use sockets and SYSV IPC shared memory,
211      there's a good chance that a duplicated socket in the child occupies
212      memory which is needed to duplicate shared memory from the parent
213      process, if the shared memory hasn't been duplicated already.
214      The same goes very likely for "normal" mmap shared memory, too, but
215      with SYSV IPC it was the first time observed.  So, *never* fixup
216      fdtab before fixing up shared memory. */
217   if (fixup_shms_after_fork ())
218     api_fatal ("recreate_shm areas after fork failed");
219 #endif
220
221   MALLOC_CHECK;
222
223   /* If we haven't dynamically loaded any dlls, just signal
224      the parent.  Otherwise, load all the dlls, tell the parent
225       that we're done, and wait for the parent to fill in the.
226       loaded dlls' data/bss. */
227   if (!load_dlls)
228     {
229       cygheap->fdtab.fixup_after_fork (hParent);
230       sync_with_parent ("performed fork fixup", false);
231     }
232   else
233     {
234       dlls.load_after_fork (hParent, first_dll);
235       cygheap->fdtab.fixup_after_fork (hParent);
236       sync_with_parent ("loaded dlls", true);
237     }
238
239   (void) ForceCloseHandle1 (fork_info->forker_finished, forker_finished);
240
241   _my_tls.fixup_after_fork ();
242   sigproc_init ();
243
244   pthread::atforkchild ();
245   fixup_timers_after_fork ();
246   fixup_hooks_after_fork ();
247   cygbench ("fork-child");
248   cygwin_finished_initializing = true;
249   return 0;
250 }
251
252 #ifndef NO_SLOW_PID_REUSE
253 static void
254 slow_pid_reuse (HANDLE h)
255 {
256   static NO_COPY HANDLE last_fork_procs[NPIDS_HELD];
257   static NO_COPY unsigned nfork_procs;
258
259   if (nfork_procs >= (sizeof (last_fork_procs) / sizeof (last_fork_procs [0])))
260     nfork_procs = 0;
261   /* Keep a list of handles to child processes sitting around to prevent
262      Windows from reusing the same pid n times in a row.  Having the same pids
263      close in succesion confuses bash.  Keeping a handle open will stop
264      windows from reusing the same pid.  */
265   if (last_fork_procs[nfork_procs])
266     ForceCloseHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
267   if (DuplicateHandle (hMainProc, h, hMainProc, &last_fork_procs[nfork_procs],
268                         0, FALSE, DUPLICATE_SAME_ACCESS))
269     ProtectHandle1 (last_fork_procs[nfork_procs], fork_stupidity);
270   else
271     {
272       last_fork_procs[nfork_procs] = NULL;
273       system_printf ("couldn't create last_fork_proc, %E");
274     }
275   nfork_procs++;
276 }
277 #endif
278
279 static int __stdcall
280 fork_parent (HANDLE&, dll *&first_dll, bool& load_dlls, void *stack_here, child_info_fork &ch)
281 {
282   HANDLE forker_finished;
283   DWORD rc;
284   PROCESS_INFORMATION pi = {0, NULL, 0, 0};
285
286   pthread::atforkprepare ();
287
288   int c_flags = GetPriorityClass (hMainProc) /*|
289                 CREATE_NEW_PROCESS_GROUP*/;
290   STARTUPINFO si = {0, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL};
291
292   /* If we don't have a console, then don't create a console for the
293      child either.  */
294   HANDLE console_handle = CreateFile ("CONOUT$", GENERIC_WRITE,
295                                       FILE_SHARE_WRITE, &sec_none_nih,
296                                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
297                                       NULL);
298
299   if (console_handle != INVALID_HANDLE_VALUE)
300     CloseHandle (console_handle);
301   else
302     c_flags |= DETACHED_PROCESS;
303
304   /* Some file types (currently only sockets) need extra effort in the
305      parent after CreateProcess and before copying the datastructures
306      to the child. So we have to start the child in suspend state,
307      unfortunately, to avoid a race condition. */
308   if (cygheap->fdtab.need_fixup_before ())
309     c_flags |= CREATE_SUSPENDED;
310
311   /* Remember the address of the first loaded dll and decide
312      if we need to load dlls.  We do this here so that this
313      information will be available in the parent and, when
314      the stack is copied, in the child. */
315   first_dll = dlls.start.next;
316   load_dlls = dlls.reload_on_fork && dlls.loaded_dlls;
317
318   /* This will help some of the confusion.  */
319   fflush (stdout);
320
321   forker_finished = CreateEvent (&sec_all, FALSE, FALSE, NULL);
322   if (forker_finished == NULL)
323     {
324       system_printf ("unable to allocate forker_finished event, %E");
325       return -1;
326     }
327
328   ProtectHandleINH (forker_finished);
329
330   ch.forker_finished = forker_finished;
331
332   stack_base (ch);
333
334   si.cb = sizeof (STARTUPINFO);
335   si.lpReserved2 = (LPBYTE) &ch;
336   si.cbReserved2 = sizeof (ch);
337
338   /* Remove impersonation */
339   cygheap->user.deimpersonate ();
340
341   syscall_printf ("CreateProcess (%s, %s, 0, 0, 1, %x, 0, 0, %p, %p)",
342                   myself->progname, myself->progname, c_flags, &si, &pi);
343   bool locked = __malloc_lock ();
344   rc = CreateProcess (myself->progname, /* image to run */
345                       myself->progname, /* what we send in arg0 */
346                       &sec_none_nih,
347                       &sec_none_nih,
348                       TRUE,       /* inherit handles from parent */
349                       c_flags,
350                       NULL,       /* environment filled in later */
351                       0,          /* use current drive/directory */
352                       &si,
353                       &pi);
354
355   if (!rc)
356     {
357       __seterrno ();
358       syscall_printf ("CreateProcessA failed, %E");
359       ForceCloseHandle (forker_finished);
360       /* Restore impersonation */
361       cygheap->user.reimpersonate ();
362       __malloc_unlock ();
363       return -1;
364     }
365
366   /* Fixup the parent datastructure if needed and resume the child's
367      main thread. */
368   if (cygheap->fdtab.need_fixup_before ())
369     {
370       cygheap->fdtab.fixup_before_fork (pi.dwProcessId);
371       ResumeThread (pi.hThread);
372     }
373
374   int child_pid = cygwin_pid (pi.dwProcessId);
375   pinfo child (child_pid, 1);
376   child->start_time = time (NULL); /* Register child's starting time. */
377   child->nice = myself->nice;
378
379   if (!child)
380     {
381       syscall_printf ("pinfo failed");
382       if (get_errno () != ENOMEM)
383         set_errno (EAGAIN);
384       goto cleanup;
385     }
386
387   /* Initialize things that are done later in dll_crt0_1 that aren't done
388      for the forkee.  */
389   strcpy (child->progname, myself->progname);
390
391   /* Restore impersonation */
392   cygheap->user.reimpersonate ();
393
394   ProtectHandle (pi.hThread);
395   /* Protect the handle but name it similarly to the way it will
396      be called in subproc handling. */
397   ProtectHandle1 (pi.hProcess, childhProc);
398
399   /* Fill in fields in the child's process table entry.  */
400   child->dwProcessId = pi.dwProcessId;
401   child.hProcess = pi.hProcess;
402
403   /* Hopefully, this will succeed.  The alternative to doing things this
404      way is to reserve space prior to calling CreateProcess and then fill
405      it in afterwards.  This requires more bookkeeping than I like, though,
406      so we'll just do it the easy way.  So, terminate any child process if
407      we can't actually record the pid in the internal table. */
408   if (!child.remember (false))
409     {
410       TerminateProcess (pi.hProcess, 1);
411       set_errno (EAGAIN);
412       goto cleanup;
413     }
414
415 #ifndef NO_SLOW_PID_REUSE
416   slow_pid_reuse (pi.hProcess);
417 #endif
418
419   /* Wait for subproc to initialize itself. */
420   if (!ch.sync (child, FORK_WAIT_TIMEOUT))
421     {
422       system_printf ("child %d died waiting for longjmp before initialization", child_pid);
423       goto cleanup;
424     }
425
426   /* CHILD IS STOPPED */
427   debug_printf ("child is alive (but stopped)");
428
429   /* Initialize, in order: data, bss, heap, stack, dll data, dll bss
430      Note: variables marked as NO_COPY will not be copied
431      since they are placed in a protected segment. */
432
433
434   MALLOC_CHECK;
435   void *impure_beg;
436   void *impure_end;
437   if (&_my_tls == _main_tls)
438     impure_beg = impure_end = NULL;
439   else
440     {
441       impure_beg = _impure_ptr;
442       impure_end = _impure_ptr + 1;
443     }
444   rc = fork_copy (pi, "user/cygwin data",
445                   user_data->data_start, user_data->data_end,
446                   user_data->bss_start, user_data->bss_end,
447                   cygheap->user_heap.base, cygheap->user_heap.ptr,
448                   stack_here, ch.stackbottom,
449                   dll_data_start, dll_data_end,
450                   dll_bss_start, dll_bss_end, impure_beg, impure_end, NULL);
451
452   __malloc_unlock ();
453   locked = false;
454   MALLOC_CHECK;
455   if (!rc)
456     goto cleanup;
457
458   /* Now fill data/bss of any DLLs that were linked into the program. */
459   for (dll *d = dlls.istart (DLL_LINK); d; d = dlls.inext ())
460     {
461       debug_printf ("copying data/bss of a linked dll");
462       if (!fork_copy (pi, "linked dll data/bss", d->p.data_start, d->p.data_end,
463                                                  d->p.bss_start, d->p.bss_end,
464                                                  NULL))
465         goto cleanup;
466     }
467
468   /* Start thread, and wait for it to reload dlls.  */
469   if (!resume_child (forker_finished))
470     goto cleanup;
471   else if (!ch.sync (child, FORK_WAIT_TIMEOUT))
472     {
473       system_printf ("child %d died waiting for dll loading", child_pid);
474       goto cleanup;
475     }
476
477   /* If DLLs were loaded in the parent, then the child has reloaded all
478      of them and is now waiting to have all of the individual data and
479      bss sections filled in. */
480   if (load_dlls)
481     {
482       /* CHILD IS STOPPED */
483       /* write memory of reloaded dlls */
484       for (dll *d = dlls.istart (DLL_LOAD); d; d = dlls.inext ())
485         {
486           debug_printf ("copying data/bss for a loaded dll");
487           if (!fork_copy (pi, "loaded dll data/bss", d->p.data_start, d->p.data_end,
488                                                      d->p.bss_start, d->p.bss_end,
489                                                      NULL))
490             goto cleanup;
491         }
492       /* Start the child up again. */
493       (void) resume_child (forker_finished);
494     }
495
496   ForceCloseHandle (pi.hThread);
497   ForceCloseHandle (forker_finished);
498   forker_finished = NULL;
499   pi.hThread = NULL;
500   pthread::atforkparent ();
501
502   return child_pid;
503
504 /* Common cleanup code for failure cases */
505  cleanup:
506   if (locked)
507     __malloc_unlock ();
508
509   /* Remember to de-allocate the fd table. */
510   if (pi.hProcess)
511     ForceCloseHandle1 (pi.hProcess, childhProc);
512   if (pi.hThread)
513     ForceCloseHandle (pi.hThread);
514   if (forker_finished)
515     ForceCloseHandle (forker_finished);
516   return -1;
517 }
518
519 extern "C" int
520 fork ()
521 {
522   struct
523   {
524     dll *first_dll;
525     bool load_dlls;
526     child_info_fork ch;
527   } grouped;
528
529   MALLOC_CHECK;
530
531   debug_printf ("entering");
532   grouped.first_dll = NULL;
533   grouped.load_dlls = 0;
534
535   void *esp;
536   __asm__ volatile ("movl %%esp,%0": "=r" (esp));
537
538   myself->set_has_pgid_children ();
539
540   if (grouped.ch.parent == NULL)
541     return -1;
542   if (grouped.ch.subproc_ready == NULL)
543     {
544       system_printf ("unable to allocate subproc_ready event, %E");
545       return -1;
546     }
547
548   sig_send (NULL, __SIGHOLD);
549   int res = setjmp (grouped.ch.jmp);
550   if (res)
551     res = fork_child (grouped.ch.parent, grouped.first_dll, grouped.load_dlls);
552   else
553     res = fork_parent (grouped.ch.parent, grouped.first_dll, grouped.load_dlls, esp, grouped.ch);
554   sig_send (NULL, __SIGNOHOLD);
555
556   MALLOC_CHECK;
557   syscall_printf ("%d = fork()", res);
558   return res;
559 }
560 #ifdef DEBUGGING
561 void
562 fork_init ()
563 {
564 }
565 #endif /*DEBUGGING*/
566
567 #ifdef NEWVFORK
568 /* Dummy function to force second assignment below to actually be
569    carried out */
570 static vfork_save *
571 get_vfork_val ()
572 {
573   return vfork_storage.val ();
574 }
575 #endif
576
577 extern "C" int
578 vfork ()
579 {
580 #ifndef NEWVFORK
581   debug_printf ("stub called");
582   return fork ();
583 #else
584   vfork_save *vf = get_vfork_val ();
585   char **esp, **pp;
586
587   if (vf == NULL)
588     vf = vfork_storage.create ();
589   else if (vf->pid)
590     return fork ();
591
592   // FIXME the tls stuff could introduce a signal race if a child process
593   // exits quickly.
594   if (!setjmp (vf->j))
595     {
596       vf->pid = -1;
597       __asm__ volatile ("movl %%esp,%0": "=r" (vf->vfork_esp):);
598       __asm__ volatile ("movl %%ebp,%0": "=r" (vf->vfork_ebp):);
599       for (pp = (char **) vf->frame, esp = vf->vfork_esp;
600            esp <= vf->vfork_ebp + 2; pp++, esp++)
601         *pp = *esp;
602       vf->ctty = myself->ctty;
603       vf->sid = myself->sid;
604       vf->pgid = myself->pgid;
605       cygheap->ctty_on_hold = cygheap->ctty;
606       vf->open_fhs = cygheap->open_fhs;
607       debug_printf ("cygheap->ctty_on_hold %p, cygheap->open_fhs %d", cygheap->ctty_on_hold, cygheap->open_fhs);
608       int res = cygheap->fdtab.vfork_child_dup () ? 0 : -1;
609       debug_printf ("%d = vfork()", res);
610       _my_tls.call_signal_handler ();   // FIXME: racy
611       vf->tls = _my_tls;
612       return res;
613     }
614
615   vf = get_vfork_val ();
616
617   for (pp = (char **) vf->frame, esp = vf->vfork_esp;
618        esp <= vf->vfork_ebp + 2; pp++, esp++)
619     *esp = *pp;
620
621   cygheap->fdtab.vfork_parent_restore ();
622
623   myself->ctty = vf->ctty;
624   myself->sid = vf->sid;
625   myself->pgid = vf->pgid;
626   termios_printf ("cygheap->ctty %p, cygheap->ctty_on_hold %p", cygheap->ctty, cygheap->ctty_on_hold);
627   cygheap->open_fhs = vf->open_fhs;
628
629   if (vf->pid < 0)
630     {
631       int exitval = vf->exitval;
632       vf->pid = 0;
633       if ((vf->pid = fork ()) == 0)
634         exit (exitval);
635     }
636
637   int pid = vf->pid;
638   vf->pid = 0;
639   debug_printf ("exiting vfork, pid %d", pid);
640   sig_dispatch_pending ();
641
642   _my_tls.call_signal_handler ();       // FIXME: racy
643   _my_tls = vf->tls;
644   return pid;
645 #endif
646 }
647
648 int
649 child_copy (HANDLE h, DWORD pid, const char *what, void *child_start, void *child_end)
650 {
651   PROCESS_INFORMATION pi;
652   pi.hProcess = h;
653   pi.dwProcessId = pid;
654   pi.hThread = NULL;
655   debug_printf ("%s, start %p, end %p", what, child_start, child_end);
656   return fork_copy (pi, what, child_start, child_end, NULL);
657 }