OSDN Git Service

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