OSDN Git Service

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