OSDN Git Service

* strace.h: Add kludgy workarounds to avoid using deprecated methods for
[pf3gnuchains/pf3gnuchains3x.git] / winsup / cygwin / sigproc.cc
1 /* sigproc.cc: inter/intra signal and sub process handler
2
3    Copyright 1997, 1998, 1999, 2000 Cygnus Solutions.
4
5    Written by Christopher Faylor <cgf@cygnus.com>
6
7 This file is part of Cygwin.
8
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
11 details. */
12
13 #include <stdlib.h>
14 #include <time.h>
15 #include <sys/wait.h>
16 #include <errno.h>
17 #include <stdlib.h>
18 #include "winsup.h"
19
20 extern BOOL allow_ntsec;
21
22 /*
23  * Convenience defines
24  */
25 #define WSSC               60000 // Wait for signal completion
26 #define WPSP               40000 // Wait for proc_subproc mutex
27 #define WSPX               20000 // Wait for wait_sig to terminate
28 #define WWSP               20000 // Wait for wait_subproc to terminate
29
30 #define WAIT_SIG_PRIORITY               THREAD_PRIORITY_NORMAL
31
32 #define TOTSIGS (NSIG + __SIGOFFSET)
33
34 #define wake_wait_subproc() SetEvent (events[0])
35
36 #define no_signals_available() (!hwait_sig || !sig_loop_wait)
37
38 /*
39  * Global variables
40  */
41 const char *__sp_fn ;
42 int __sp_ln;
43
44 char NO_COPY myself_nowait_dummy[1] = {'0'};// Flag to sig_send that signal goes to
45                                         //  current process but no wait is required
46 char NO_COPY myself_nowait_nonmain_dummy[1] = {'1'};// Flag to sig_send that signal goes to
47                                         //  current process but no wait is required
48                                         //  if this is not the main thread.
49
50 HANDLE NO_COPY signal_arrived;          // Event signaled when a signal has
51                                         //  resulted in a user-specified
52                                         //  function call
53 /*
54  * Common variables
55  */
56
57
58 /* How long to wait for message/signals.  Normally this is infinite.
59  * On termination, however, these are set to zero as a flag to exit.
60  */
61
62 #define Static static NO_COPY
63
64 Static DWORD proc_loop_wait = 500;      // Wait for subprocesses to exit
65 Static DWORD sig_loop_wait = 500;       // Wait for signals to arrive
66
67 Static HANDLE sigcatch_nonmain = NULL;  // The semaphore signaled when
68                                         //  signals are available for
69                                         //  processing from non-main thread
70 Static HANDLE sigcatch_main = NULL;     // Signalled when main thread sends a
71                                         //  signal
72 Static HANDLE sigcatch_nosync = NULL;   // Signal wait_sig to scan sigtodo
73                                         //  but not to bother with any
74                                         //  synchronization
75 Static HANDLE sigcomplete_main = NULL;  // Event signaled when a signal has
76                                         //  finished processing for the main
77                                         //  thread
78 Static HANDLE sigcomplete_nonmain = NULL;// Semaphore raised for non-main
79                                         //  threads when a signal has finished
80                                         //  processing
81 Static HANDLE hwait_sig = NULL;         // Handle of wait_sig thread
82 Static HANDLE hwait_subproc = NULL;     // Handle of sig_subproc thread
83
84 Static HANDLE wait_sig_inited = NULL;   // Control synchronization of
85                                         //  message queue startup
86
87 /* Used by WaitForMultipleObjects.  These are handles to child processes.
88  */
89 Static HANDLE events[PSIZE + 1] = {0};  // All my children's handles++
90 #define hchildren (events + 1)          // Where the children handles begin
91 Static pinfo pchildren[PSIZE] = {pinfo ()};// All my children info
92 Static pinfo zombies[PSIZE] = {pinfo ()};       // All my deceased children info
93 Static int nchildren = 0;               // Number of active children
94 Static int nzombies = 0;                // Number of deceased children
95
96 Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
97 Static waitq waitq_main;                // Storage for main thread
98
99 muto NO_COPY *sync_proc_subproc = NULL; // Control access to subproc stuff
100
101 DWORD NO_COPY sigtid = 0;               // ID of the signal thread
102
103 int NO_COPY pending_signals = 0;        // TRUE if signals pending
104
105 /* Functions
106  */
107 static int __stdcall checkstate (waitq *);
108 static __inline__ BOOL get_proc_lock (DWORD, DWORD);
109 static HANDLE __stdcall getsem (_pinfo *, const char *, int, int);
110 static void __stdcall remove_child (int);
111 static void __stdcall remove_zombie (int);
112 static DWORD WINAPI wait_sig (VOID *arg);
113 static int __stdcall stopped_or_terminated (waitq *, _pinfo *);
114 static DWORD WINAPI wait_subproc (VOID *);
115
116 /* Determine if the parent process is alive.
117  */
118
119 BOOL __stdcall
120 my_parent_is_alive ()
121 {
122   DWORD res;
123   if (!parent_alive)
124     {
125       debug_printf ("No parent_alive mutex");
126       res = FALSE;
127     }
128   else
129     for (int i = 0; i < 2; i++)
130       switch (res = WaitForSingleObject (parent_alive, 0))
131         {
132           case WAIT_OBJECT_0:
133             debug_printf ("parent dead.");
134             res = FALSE;
135             goto out;
136           case WAIT_TIMEOUT:
137             debug_printf ("parent still alive");
138             res = TRUE;
139             goto out;
140           case WAIT_FAILED:
141             DWORD werr = GetLastError ();
142             if (werr == ERROR_INVALID_HANDLE && i == 0)
143               continue;
144             system_printf ("WFSO for parent_alive(%p) failed, error %d",
145                            parent_alive, werr);
146             res = FALSE;
147             goto out;
148         }
149 out:
150   return res;
151 }
152
153 __inline static void
154 wait_for_me ()
155 {
156   /* See if this is the first signal call after initialization.
157    * If so, wait for notification that all initialization has completed.
158    * Then set the handle to NULL to avoid checking this again.
159    */
160   if (wait_sig_inited)
161     {
162       (void) WaitForSingleObject (wait_sig_inited, INFINITE);
163       (void) ForceCloseHandle (wait_sig_inited);
164       wait_sig_inited = NULL;
165     }
166 }
167
168 static BOOL __stdcall
169 proc_can_be_signalled (_pinfo *p)
170 {
171   if (p == myself_nowait || p == myself_nowait_nonmain || p == myself)
172     {
173       wait_for_me ();
174       return 1;
175     }
176
177   return ISSTATE (p, PID_INITIALIZING) ||
178          (((p)->process_state & (PID_ACTIVE | PID_IN_USE)) ==
179           (PID_ACTIVE | PID_IN_USE));
180 }
181
182 BOOL __stdcall
183 proc_exists (pid_t pid)
184 {
185   pinfo p (pid);
186   return proc_exists (p);
187 }
188
189 /* Test to determine if a process really exists and is processing
190  * signals.
191  */
192 BOOL __stdcall
193 proc_exists (_pinfo *p)
194 {
195   HANDLE h;
196
197   if (p == NULL)
198     return FALSE;
199
200   if (p == myself || p == myself_nowait_nonmain || p == myself_nowait)
201     return TRUE;
202
203   if (p->process_state == PID_NOT_IN_USE || !p->dwProcessId)
204     return FALSE;
205
206   sigproc_printf ("checking for existence of pid %d, window pid %d", p->pid,
207               p->dwProcessId);
208   if (p->ppid == myself->pid && p->hProcess != NULL)
209     {
210       sigproc_printf ("it's mine, process_state %x", p->process_state);
211       return proc_can_be_signalled (p);
212     }
213
214   /* Note: Process is alive if OpenProcess() call fails due to permissions */
215   if (((h = OpenProcess (STANDARD_RIGHTS_REQUIRED, FALSE, p->dwProcessId))
216       != NULL) || (GetLastError () == ERROR_ACCESS_DENIED))
217     {
218       sigproc_printf ("it exists, %p", h);
219       if (h)
220         {
221           DWORD rc = WaitForSingleObject (h, 0);
222           CloseHandle (h);
223           if (rc == WAIT_OBJECT_0)
224             return 0;
225         }
226       return proc_can_be_signalled (p);
227     }
228
229   sigproc_printf ("it doesn't exist");
230   /* If the parent pid does not exist, clean this process out of the pinfo
231    * table.  It must have died abnormally.
232    */
233   if ((p->pid == p->ppid) || (p->ppid == 1) || !proc_exists (p->ppid))
234     {
235       p->hProcess = NULL;
236       p->process_state = PID_NOT_IN_USE;
237     }
238   return FALSE;
239 }
240
241 /* Handle all subprocess requests
242  */
243 #define vchild (*((pinfo *) val))
244 int __stdcall
245 proc_subproc (DWORD what, DWORD val)
246 {
247   int rc = 1;
248   int potential_match;
249   DWORD exitcode;
250   _pinfo *child;
251   int clearing;
252   waitq *w;
253
254 #define wval     ((waitq *) val)
255
256   sigproc_printf ("args: %x, %d", what, val);
257
258   if (!get_proc_lock (what, val))       // Serialize access to this function
259     {
260       sigproc_printf ("I am not ready");
261       goto out1;
262     }
263
264   switch (what)
265     {
266     /* Add a new subprocess to the children arrays.
267      * (usually called from the main thread)
268      */
269     case PROC_ADDCHILD:
270       if (nchildren >= PSIZE - 1)
271         system_printf ("nchildren too large %d", nchildren);
272       if (WaitForSingleObject (vchild->hProcess, 0) != WAIT_TIMEOUT)
273         {
274           system_printf ("invalid process handle %p.  pid %d, win pid %d",
275                         vchild->hProcess, vchild->pid, vchild->dwProcessId);
276           rc = 0;
277           break;
278         }
279
280       pchildren[nchildren] = vchild;
281       hchildren[nchildren] = vchild->hProcess;
282       ProtectHandle1 (vchild->hProcess, childhProc);
283       sigproc_printf ("added pid %d to wait list, slot %d, winpid %p, handle %p",
284                   vchild->pid, nchildren, vchild->dwProcessId,
285                   vchild->hProcess);
286
287       nchildren++;
288       wake_wait_subproc ();
289       break;
290
291     /* A child process had terminated.
292      * Possibly this is just due to an exec().  Cygwin implements an exec()
293      * as a "handoff" from one windows process to another.  If child->hProcess
294      * is different from what is recorded in hchildren, then this is an exec().
295      * Otherwise this is a normal child termination event.
296      * (called from wait_subproc thread)
297      */
298     case PROC_CHILDTERMINATED:
299       rc = 0;
300       if (GetExitCodeProcess (hchildren[val], &exitcode) &&
301           hchildren[val] != pchildren[val]->hProcess)
302         {
303           sigproc_printf ("pid %d[%d], reparented old hProcess %p, new %p",
304                       pchildren[val]->pid, val, hchildren[val], pchildren[val]->hProcess);
305           ForceCloseHandle1 (hchildren[val], childhProc);
306           hchildren[val] = pchildren[val]->hProcess; /* Filled out by child */
307           ProtectHandle1 (pchildren[val]->hProcess, childhProc);
308           break;                        // This was an exec()
309         }
310
311       sigproc_printf ("pid %d[%d] terminated, handle %p, nchildren %d, nzombies %d",
312                   pchildren[val]->pid, val, hchildren[val], nchildren, nzombies);
313       zombies[nzombies] = pchildren[val];       // Add to zombie array
314       zombies[nzombies++]->process_state = PID_ZOMBIE;// Walking dead
315       remove_child (val);               // Remove from children array
316       if (!proc_loop_wait)              // Don't bother if wait_subproc is
317         break;                          //  exiting
318
319       /* Send a SIGCHLD to myself. */
320       rc = sig_send (myself_nowait, SIGCHLD);   // Send a SIGCHLD
321       break;
322
323     /* A child is in the stopped state.  Scan wait() queue to see if anyone
324      * should be notified.  (Called from wait_sig thread)
325      */
326     case PROC_CHILDSTOPPED:
327       child = myself;           // Just to avoid accidental NULL dereference
328       sigproc_printf ("Received stopped notification");
329       clearing = 0;
330       goto scan_wait;
331
332     /* Clear all waiting threads.  Called from exceptions.cc prior to
333      * the main thread's dispatch to a signal handler function.
334      * (called from wait_sig thread)
335      */
336     case PROC_CLEARWAIT:
337       /* Clear all "wait"ing threads. */
338       if (val)
339         sigproc_printf ("clear waiting threads");
340       else
341         sigproc_printf ("looking for processes to reap");
342       clearing = val;
343
344     scan_wait:
345       /* Scan the linked list of wait()ing threads.  If a wait's parameters
346        * match this pid, then activate it.
347        */
348       for (w = &waitq_head; w->next != NULL; w = w->next)
349         {
350           if ((potential_match = checkstate (w)) > 0)
351             sigproc_printf ("released waiting thread");
352           else if (!clearing && potential_match < 0)
353             sigproc_printf ("only found non-terminated children");
354           else if (potential_match <= 0)                // nothing matched
355             {
356               sigproc_printf ("waiting thread found no children");
357               HANDLE oldw = w->next->ev;
358               if (clearing)
359                 w->next->status = -1;           /* flag that a signal was received */
360               else
361                 w->next->ev = NULL;
362               if (!SetEvent (oldw))
363                 system_printf ("couldn't wake up wait event %p, %E", oldw);
364               w->next = w->next->next;
365             }
366           if (w->next == NULL)
367             break;
368         }
369
370       if (!clearing)
371         sigproc_printf ("finished processing terminated/stopped child");
372       else
373         {
374           waitq_head.next = NULL;
375           sigproc_printf ("finished clearing");
376         }
377       break;
378
379     /* Handle a wait4() operation.  Allocates an event for the calling
380      * thread which is signaled when the appropriate pid exits or stops.
381      * (usually called from the main thread)
382      */
383     case PROC_WAIT:
384       wval->ev = NULL;          // Don't know event flag yet
385
386       if (wval->pid <= 0)
387         child = NULL;           // Not looking for a specific pid
388       else if (!proc_exists (wval->pid)) /* CGF FIXME -- test that this is one of mine */
389         goto out;               // invalid pid.  flag no such child
390
391       wval->status = 0;         // Don't know status yet
392
393       /* Put waitq structure at the end of a linked list. */
394       for (w = &waitq_head; w->next != NULL; w = w->next)
395         if (w->next == wval && (w->next = w->next->next) == NULL)
396           break;
397
398       wval->next = NULL;        /* This will be last in the list */
399       sigproc_printf ("wval->pid %d, wval->options %d", wval->pid, wval->options);
400
401       /* If the first time for this thread, create a new event, otherwise
402        * reset the event.
403        */
404       if ((wval->ev = wval->thread_ev) == NULL)
405         {
406           wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE,
407                                                     FALSE, NULL);
408           ProtectHandle (wval->ev);
409         }
410       ResetEvent (wval->ev);
411
412       /* Scan list of children to see if any have died.
413        * If so, the event flag is set so that the wait* ()
414        * process will return immediately.
415        *
416        * If no children were found and the wait option was WNOHANG,
417        * then set the pid to 0 and remove the waitq value from
418        * consideration.
419        */
420       w->next = wval;           /* set at end of wait queue */
421       if ((potential_match = checkstate (w)) <= 0)
422         {
423           if (!potential_match)
424             {
425               w->next = NULL;           // don't want to keep looking
426               wval->ev = NULL;          // flag that there are no children
427               sigproc_printf ("no appropriate children, %p, %p",
428                           wval->thread_ev, wval->ev);
429             }
430           else if (wval->options & WNOHANG)
431             {
432               w->next = NULL;           // don't want to keep looking
433               wval->pid = 0;            // didn't find a pid
434               if (!SetEvent (wval->ev)) // wake up wait4 () immediately
435                 system_printf ("Couldn't wake up wait event, %E");
436               sigproc_printf ("WNOHANG and no terminated children, %p, %p",
437                           wval->thread_ev, wval->ev);
438             }
439         }
440       if (w->next != NULL)
441         sigproc_printf ("wait activated %p, %p", wval->thread_ev, wval->ev);
442       else if (wval->ev != NULL)
443         sigproc_printf ("wait activated %p.  Reaped zombie.", wval->ev);
444       else
445         sigproc_printf ("wait not activated %p, %p", wval->thread_ev, wval->ev);
446       break;
447   }
448
449 out:
450   sync_proc_subproc->release ();        // Release the lock
451 out1:
452   sigproc_printf ("returning %d", rc);
453   return rc;
454 }
455
456 /* Terminate the wait_subproc thread.
457  * Called on process exit.
458  * Also called by spawn_guts to disassociate any subprocesses from this
459  * process.  Subprocesses will then know to clean up after themselves and
460  * will not become zombies.
461  */
462 void __stdcall
463 proc_terminate (void)
464 {
465   sigproc_printf ("nchildren %d, nzombies %d", nchildren, nzombies);
466   /* Signal processing is assumed to be blocked in this routine. */
467   if (hwait_subproc)
468     {
469       int rc;
470       proc_loop_wait = 0;       // Tell wait_subproc thread to exit
471       wake_wait_subproc ();     // Wake wait_subproc loop
472
473       /* Wait for wait_subproc thread to exit (but not *too* long) */
474       if ((rc = WaitForSingleObject (hwait_subproc, WWSP)) != WAIT_OBJECT_0)
475         if (rc == WAIT_TIMEOUT)
476           system_printf ("WFSO(hwait_subproc) timed out");
477         else
478           system_printf ("WFSO(hwait_subproc), rc %d, %E", rc);
479
480       HANDLE h = hwait_subproc;
481       hwait_subproc = NULL;
482       ForceCloseHandle1 (h, hwait_subproc);
483
484       sync_proc_subproc->acquire(WPSP);
485       (void) proc_subproc (PROC_CLEARWAIT, 1);
486
487       /* Clean out zombie processes from the pid list. */
488       int i;
489       for (i = 0; i < nzombies; i++)
490         {
491           if (zombies[i]->hProcess)
492             {
493               ForceCloseHandle1 (zombies[i]->hProcess, childhProc);
494               zombies[i]->hProcess = NULL;
495             }
496           zombies[i]->process_state = PID_NOT_IN_USE;   /* CGF FIXME - still needed? */
497           zombies[i].release();
498         }
499
500       /* Disassociate my subprocesses */
501       for (i = 0; i < nchildren; i++)
502         {
503           pinfo child; /* CGF FIXME */
504           if (pchildren[i]->process_state == PID_NOT_IN_USE)
505             continue;           // Should never happen
506           if (!pchildren[i]->hProcess)
507             sigproc_printf ("%d(%d) hProcess cleared already?", pchildren[i]->pid,
508                         pchildren[i]->dwProcessId);
509           else
510             {
511               ForceCloseHandle1 (pchildren[i]->hProcess, childhProc);
512               pchildren[i]->hProcess = NULL;
513               if (!proc_exists (pchildren[i]))
514                 {
515                   sigproc_printf ("%d(%d) doesn't exist", pchildren[i]->pid,
516                               pchildren[i]->dwProcessId);
517                   pchildren[i]->process_state = PID_NOT_IN_USE; /* a reaped child  CGF FIXME -- still needed? */
518                 }
519               else
520                 {
521                   sigproc_printf ("%d(%d) closing active child handle", pchildren[i]->pid,
522                               pchildren[i]->dwProcessId);
523                   pchildren[i]->ppid = 1;
524                   if (pchildren[i]->pgid == myself->pid)
525                     pchildren[i]->process_state |= PID_ORPHANED;
526                 }
527             }
528           pchildren[i].release ();
529         }
530       nchildren = nzombies = 0;
531
532       /* Attempt to close and release sync_proc_subproc in a
533        * non-raceable manner.
534        */
535       muto *m = sync_proc_subproc;
536       if (m)
537         {
538           sync_proc_subproc = NULL;
539           delete m;
540         }
541     }
542   sigproc_printf ("leaving");
543 }
544
545 /* Clear pending signal from the sigtodo array
546  */
547 void __stdcall
548 sig_clear (int sig)
549 {
550   (void) InterlockedExchange (myself->getsigtodo(sig), 0L);
551   return;
552 }
553
554 /* Force the wait_sig thread to wake up and scan the sigtodo array.
555  */
556 extern "C" int __stdcall
557 sig_dispatch_pending (int justwake)
558 {
559   if (!hwait_sig)
560     return 0;
561
562   int was_pending = pending_signals;
563 #ifdef DEBUGGING
564   sigproc_printf ("pending_signals %d", was_pending);
565 #endif
566   if (!was_pending && !justwake)
567 #ifdef DEBUGGING
568     sigproc_printf ("no need to wake anything up");
569 #else
570     ;
571 #endif
572   else
573     {
574       wait_for_me ();
575       if (!justwake)
576         (void) sig_send (myself, __SIGFLUSH);
577       else if (ReleaseSemaphore (sigcatch_nosync, 1, NULL))
578 #ifdef DEBUGGING
579         sigproc_printf ("woke up wait_sig");
580 #else
581         ;
582 #endif
583       else if (no_signals_available ())
584         /*sigproc_printf ("I'm going away now")*/;
585       else
586         system_printf ("%E releasing sigcatch_nosync(%p)", sigcatch_nosync);
587  
588     }
589   return was_pending;
590 }
591
592 /* Message initialization.  Called from dll_crt0_1
593  *
594  * This routine starts the signal handling thread.  The wait_sig_inited
595  * event is used to signal that the thread is ready to handle signals.
596  * We don't wait for this during initialization but instead detect it
597  * in sig_send to gain a little concurrency.
598  */
599 void __stdcall
600 sigproc_init ()
601 {
602   wait_sig_inited = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
603   ProtectHandle (wait_sig_inited);
604
605   /* local event signaled when main thread has been dispatched
606      to a signal handler function. */
607   signal_arrived = CreateEvent(&sec_none_nih, TRUE, FALSE, NULL);
608
609   if (!(hwait_sig = makethread (wait_sig, NULL, 0, "sig")))
610     {
611       system_printf ("cannot create wait_sig thread, %E");
612       api_fatal ("terminating");
613     }
614
615   ProtectHandle (hwait_sig);
616
617   /* sync_proc_subproc is used by proc_subproc.  It serialises
618    * access to the children and zombie arrays.
619    */
620   sync_proc_subproc = new_muto (FALSE, "sync_proc_subproc");
621
622   /* Initialize waitq structure for main thread.  A waitq structure is
623    * allocated for each thread that executes a wait to allow multiple threads
624    * to perform waits.  Pre-allocate a waitq structure for the main thread.
625    */
626   waitq *w;
627   if ((w = (waitq *)waitq_storage.get ()) == NULL)
628     {
629       w = &waitq_main;
630       waitq_storage.set (w);
631     }
632   memset (w, 0, sizeof *w);     // Just to be safe
633
634   sigproc_printf ("process/signal handling enabled(%x)", myself->process_state);
635   return;
636 }
637
638 /* Called on process termination to terminate signal and process threads.
639  */
640 void __stdcall
641 sigproc_terminate (void)
642 {
643   HANDLE h = hwait_sig;
644   hwait_sig = NULL;
645
646   if (GetCurrentThreadId () == sigtid)
647     {
648       ForceCloseHandle (sigcomplete_main);
649       for (int i = 0; i < 20; i++)
650         (void) ReleaseSemaphore (sigcomplete_nonmain, 1, NULL);
651       ForceCloseHandle (sigcomplete_nonmain);
652       ForceCloseHandle (sigcatch_main);
653       ForceCloseHandle (sigcatch_nonmain);
654       ForceCloseHandle (sigcatch_nosync);
655     }
656   proc_terminate ();            // Terminate process handling thread
657
658   if (!sig_loop_wait)
659     sigproc_printf ("sigproc_terminate: sigproc handling not active");
660   else
661     {
662       sigproc_printf ("entering");
663       sig_loop_wait = 0;        // Tell wait_sig to exit when it is
664                                 //  finished with anything it is doing
665       sig_dispatch_pending (TRUE);      // wake up and die
666
667       /* If !hwait_sig, then the process probably hasn't even finished
668        * its initialization phase.
669        */
670       if (hwait_sig)
671         {
672           if (GetCurrentThreadId () != sigtid)
673             WaitForSingleObject (h, 10000);
674           ForceCloseHandle1 (h, hwait_sig);
675
676           /* Exiting thread.  Cleanup.  Don't set to inactive if a child has been
677              execed with the same pid. */
678           if (!myself->dwProcessId || myself->dwProcessId == GetCurrentProcessId ())
679             myself->process_state &= ~PID_ACTIVE;
680           else
681             sigproc_printf ("Did not clear PID_ACTIVE since %d != %d",
682                         myself->dwProcessId, GetCurrentProcessId ());
683
684           /* In case of a sigsuspend */
685           SetEvent (signal_arrived);
686
687           if (GetCurrentThreadId () != sigtid)
688             {
689               ForceCloseHandle (sigcomplete_main);
690               ForceCloseHandle (sigcomplete_nonmain);
691               ForceCloseHandle (sigcatch_main);
692               ForceCloseHandle (sigcatch_nonmain);
693               ForceCloseHandle (sigcatch_nosync);
694             }
695         }
696       sigproc_printf ("done");
697     }
698
699   /* Set this so that subsequent tests will succeed. */
700   if (!myself->dwProcessId)
701     myself->dwProcessId = GetCurrentProcessId ();
702
703   return;
704 }
705
706 /* Send a signal to another process by raising its signal semaphore.
707  * If pinfo *p == NULL, send to the current process.
708  * If sending to this process, wait for notification that a signal has
709  * completed before returning.
710  */
711 int __stdcall
712 sig_send (_pinfo *p, int sig, DWORD ebp)
713 {
714   int rc = 1;
715   DWORD tid = GetCurrentThreadId ();
716   BOOL its_me;
717   HANDLE thiscatch = NULL;
718   HANDLE thiscomplete = NULL;
719   BOOL wait_for_completion;
720   sigframe thisframe;
721
722   if (p == myself_nowait_nonmain)
723     p = (tid == mainthread.id) ? (_pinfo *) myself : myself_nowait;
724   if (!(its_me = (p == NULL || p == myself || p == myself_nowait)))
725     wait_for_completion = FALSE;
726   else
727     {
728       if (no_signals_available ())
729         goto out;               // Either exiting or not yet initializing
730       wait_for_me ();
731       wait_for_completion = p != myself_nowait;
732       p = myself;
733     }
734
735   /* It is possible that the process is not yet ready to receive messages
736    * or that it has exited.  Detect this.
737    */
738   if (!proc_can_be_signalled (p))       /* Is the process accepting messages? */
739     {
740       sigproc_printf ("invalid pid %d(%x), signal %d",
741                   p->pid, p->process_state, sig);
742       set_errno (ESRCH);
743       goto out;
744     }
745
746   sigproc_printf ("pid %d, signal %d, its_me %d", p->pid, sig, its_me);
747
748   if (its_me)
749     {
750       if (!wait_for_completion)
751         thiscatch = sigcatch_nosync;
752       else if (tid != mainthread.id)
753         {
754           thiscatch = sigcatch_nonmain;
755           thiscomplete = sigcomplete_nonmain;
756         }
757       else
758         {
759           thiscatch = sigcatch_main;
760           thiscomplete = sigcomplete_main;
761           thisframe.set (mainthread, 1, ebp);
762         }
763     }
764   else if (!(thiscatch = getsem (p, "sigcatch", 0, 0)))
765     goto out;             // Couldn't get the semaphore.  getsem issued
766                           //  an error, if appropriate.
767
768 #if WHEN_MULTI_THREAD_SIGNALS_WORK
769   signal_dispatch *sd;
770   sd = signal_dispatch_storage.get ();
771   if (sd == NULL)
772     sd = signal_dispatch_storage.create ();
773 #endif
774
775   /* Increment the sigtodo array to signify which signal to assert.
776    */
777   (void) InterlockedIncrement (p->getsigtodo(sig));
778
779   /* Notify the process that a signal has arrived.
780    */
781   SetLastError (0);
782
783 #if 0
784   int prio;
785   prio = GetThreadPriority (GetCurrentThread ());
786   (void) SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_TIME_CRITICAL);
787 #endif
788
789   if (!ReleaseSemaphore (thiscatch, 1, NULL) && (int) GetLastError () > 0)
790     {
791 sigproc_printf ("ReleaseSemaphore failed, %E");
792       /* Couldn't signal the semaphore.  This probably means that the
793        * process is exiting.
794        */
795       if (!its_me)
796         ForceCloseHandle (thiscatch);
797       else
798         {
799           if (no_signals_available ())
800             sigproc_printf ("I'm going away now");
801           else if ((int) GetLastError () == -1)
802             rc = WaitForSingleObject (thiscomplete, 500);
803           else
804             system_printf ("error sending signal %d to pid %d, semaphore %p, %E",
805                           sig, p->pid, thiscatch);
806         }
807       goto out;
808     }
809 sigproc_printf ("ReleaseSemaphore succeeded");
810
811   /* No need to wait for signal completion unless this was a signal to
812    * this process.
813    *
814    * If it was a signal to this process, wait for a dispatched signal.
815    * Otherwise just wait for the wait_sig to signal that it has finished
816    * processing the signal.
817    */
818   if (!wait_for_completion)
819     {
820       rc = WAIT_OBJECT_0;
821       sigproc_printf ("Not waiting for sigcomplete.  its_me %d sig %d", its_me, sig);
822       if (!its_me)
823         ForceCloseHandle (thiscatch);
824     }
825   else
826     {
827       sigproc_printf ("Waiting for thiscomplete %p", thiscomplete);
828
829       SetLastError (0);
830       rc = WaitForSingleObject (thiscomplete, WSSC);
831       /* Check for strangeness due to this thread being redirected by the
832          signal handler.  Sometimes a WAIT_TIMEOUT will occur when the
833          thread hasn't really timed out.  So, check again.
834          FIXME: This isn't foolproof. */
835       if (rc != WAIT_OBJECT_0 &&
836           WaitForSingleObject (thiscomplete, 0) == WAIT_OBJECT_0)
837         rc = WAIT_OBJECT_0;
838     }
839
840 #if 0
841   SetThreadPriority (GetCurrentThread (), prio);
842 #endif
843
844   if (rc == WAIT_OBJECT_0)
845     rc = 0;             // Successful exit
846   else
847     {
848       /* It's an error unless sig_loop_wait == 0 (the process is exiting). */
849       if (!no_signals_available ())
850         system_printf ("wait for sig_complete event failed, sig %d, rc %d, %E",
851                       sig, rc);
852       set_errno (ENOSYS);
853       rc = -1;
854     }
855
856 out:
857   sigproc_printf ("returning %d from sending signal %d", rc, sig);
858   return rc;
859 }
860
861 /* Set pending signal from the sigtodo array
862  */
863 void __stdcall
864 sig_set_pending (int sig)
865 {
866   (void) InterlockedIncrement (myself->getsigtodo(sig));
867   return;
868 }
869
870 /* Initialize the wait_subproc thread.
871  * Called from fork() or spawn() to initialize the handling of subprocesses.
872  */
873 void __stdcall
874 subproc_init (void)
875 {
876   if (hwait_subproc)
877     return;
878
879   /* A "wakeup" handle which can be toggled to make wait_subproc reexamine
880    * the hchildren array.
881    */
882   events[0] = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
883   if (!(hwait_subproc = makethread (wait_subproc, NULL, 0, "+proc")))
884     system_printf ("cannot create wait_subproc thread, %E");
885   ProtectHandle (events[0]);
886   ProtectHandle (hwait_subproc);
887   sigproc_printf ("started wait_subproc thread %p", hwait_subproc);
888 }
889
890 /* Initialize some of the memory block passed to child processes
891    by fork/spawn/exec. */
892
893 void __stdcall
894 init_child_info (DWORD chtype, child_info *ch, pid_t pid, HANDLE subproc_ready)
895 {
896   subproc_init ();
897   memset (ch, 0, sizeof *ch);
898   ch->cb = sizeof *ch;
899   ch->type = chtype;
900   ch->cygpid = pid;
901   ch->shared_h = cygwin_shared_h;
902   ch->console_h = console_shared_h;
903   ch->subproc_ready = subproc_ready;
904   if (chtype != PROC_EXEC || !parent_alive)
905     ch->parent_alive = hwait_subproc;
906   else if (parent_alive)
907     DuplicateHandle (hMainProc, parent_alive, hMainProc, &ch->parent_alive,
908                      0, 1, DUPLICATE_SAME_ACCESS);
909 }
910
911 /* Check the state of all of our children to see if any are stopped or
912  * terminated.
913  */
914 static int __stdcall
915 checkstate (waitq *w)
916 {
917   int i, x, potential_match = 0;
918   _pinfo *child;
919
920   sigproc_printf ("nchildren %d, nzombies %d", nchildren, nzombies);
921
922   /* Check already dead processes first to see if they match the criteria
923    * given in w->next.
924    */
925   for (i = 0; i < nzombies; i++)
926     if ((x = stopped_or_terminated (w, child = zombies[i])) < 0)
927       potential_match = -1;
928     else if (x > 0)
929       {
930         remove_zombie (i);
931         potential_match = 1;
932         goto out;
933       }
934
935   sigproc_printf ("checking alive children");
936
937   /* No dead terminated children matched.  Check for stopped children. */
938   for (i = 0; i < nchildren; i++)
939     if ((x = stopped_or_terminated (w, pchildren[i])) < 0)
940       potential_match = -1;
941     else if (x > 0)
942       {
943         potential_match = 1;
944         break;
945       }
946
947 out:
948   sigproc_printf ("returning %d", potential_match);
949   return potential_match;
950 }
951
952 /* Get or create a process specific semaphore used in message passing.
953  */
954 static HANDLE __stdcall
955 getsem (_pinfo *p, const char *str, int init, int max)
956 {
957   HANDLE h;
958
959   if (p != NULL)
960     {
961       if (!proc_can_be_signalled (p))
962         {
963           set_errno (ESRCH);
964           return NULL;
965         }
966       int wait = 10000;
967       sigproc_printf ("pid %d, ppid %d, wait %d, initializing %x", p->pid, p->ppid, wait,
968                   ISSTATE (p, PID_INITIALIZING));
969       for (int i = 0; ISSTATE (p, PID_INITIALIZING) && i < wait; i++)
970         Sleep (1);
971     }
972
973   SetLastError (0);
974   if (p == NULL)
975     {
976       char sa_buf[1024];
977
978       DWORD winpid = GetCurrentProcessId ();
979       h = CreateSemaphore (allow_ntsec ? sec_user (sa_buf) : &sec_none_nih,
980                            init, max, str = shared_name (str, winpid));
981       p = myself;
982     }
983   else
984     {
985       h = OpenSemaphore (SEMAPHORE_ALL_ACCESS, FALSE,
986                          str = shared_name (str, p->dwProcessId));
987
988       if (h == NULL)
989         {
990           if (GetLastError () == ERROR_FILE_NOT_FOUND && !proc_exists (p))
991             set_errno (ESRCH);
992           else
993             set_errno (EPERM);
994           return NULL;
995         }
996     }
997
998   if (!h)
999     {
1000       system_printf ("can't %s %s, %E", p ? "open" : "create", str);
1001       set_errno (ESRCH);
1002     }
1003   return h;
1004 }
1005
1006 /* Get the sync_proc_subproc muto to control access to
1007  * children, zombie arrays.
1008  * Attempt to handle case where process is exiting as we try to grab
1009  * the mutex.
1010  */
1011 static BOOL
1012 get_proc_lock (DWORD what, DWORD val)
1013 {
1014   Static int lastwhat = -1;
1015   if (!sync_proc_subproc)
1016     return FALSE;
1017   if (sync_proc_subproc->acquire (WPSP))
1018     {
1019       lastwhat = what;
1020       return TRUE;
1021     }
1022   if (!sync_proc_subproc)
1023     return FALSE;
1024   system_printf ("Couldn't aquire sync_proc_subproc for(%d,%d), %E, last %d",
1025                   what, val, lastwhat);
1026   return TRUE;
1027 }
1028
1029 /* Remove a child from pchildren/hchildren by swapping it with the
1030  * last child in the list.
1031  */
1032 static void __stdcall
1033 remove_child (int ci)
1034 {
1035   sigproc_printf ("removing [%d], pid %d, handle %p, nchildren %d",
1036               ci, pchildren[ci]->pid, hchildren[ci], nchildren);
1037   if (ci < --nchildren)
1038     {
1039       pchildren[ci] = pchildren[nchildren];
1040       hchildren[ci] = hchildren[nchildren];
1041     }
1042
1043   return;
1044 }
1045
1046 /* Remove a zombie from zombies by swapping it with the last child in the list.
1047  */
1048 static void __stdcall
1049 remove_zombie (int ci)
1050 {
1051   sigproc_printf ("removing %d, pid %d, nzombies %d", ci, zombies[ci]->pid,
1052               nzombies);
1053
1054   if (zombies[ci])
1055     zombies[ci].release ();
1056
1057   if (ci < --nzombies)
1058     zombies[ci] = zombies[nzombies];
1059
1060   return;
1061 }
1062
1063 /* Check status of child process vs. waitq member.
1064  *
1065  * parent_w is the pointer to the parent of the waitq member in question.
1066  * child is the subprocess being considered.
1067  *
1068  * Returns
1069  *   1 if stopped or terminated child matches parent_w->next criteria
1070  *  -1 if a non-stopped/terminated child matches parent_w->next criteria
1071  *   0 if child does not match parent_w->next criteria
1072  */
1073 static int __stdcall
1074 stopped_or_terminated (waitq *parent_w, _pinfo *child)
1075 {
1076   int potential_match;
1077   waitq *w = parent_w->next;
1078
1079   sigproc_printf ("considering pid %d", child->pid);
1080   if (w->pid == -1)
1081     potential_match = 1;
1082   else if (w->pid == 0)
1083     potential_match = child->pgid == myself->pgid;
1084   else if (w->pid < 0)
1085     potential_match = child->pgid == -w->pid;
1086   else
1087     potential_match = (w->pid == child->pid);
1088
1089   if (!potential_match)
1090     return 0;
1091
1092   BOOL terminated;
1093
1094   if ((terminated = child->process_state == PID_ZOMBIE) ||
1095       (w->options & WUNTRACED) && child->stopsig)
1096     {
1097       parent_w->next = w->next; /* successful wait.  remove from wait queue */
1098       w->pid = child->pid;
1099
1100       if (!terminated)
1101         {
1102           sigproc_printf ("stopped child");
1103           w->status = (child->stopsig << 8) | 0x7f;
1104           child->stopsig = 0;
1105         }
1106       else /* Should only get here when child has been moved to the zombies array */
1107         {
1108           DWORD status;
1109           if (!GetExitCodeProcess (child->hProcess, &status))
1110             status = 0xffff;
1111           if (status & EXIT_SIGNAL)
1112             w->status = (status >> 8) & 0xff;   /* exited due to signal */
1113           else
1114             w->status = (status & 0xff) << 8;   /* exited via "exit ()" */
1115
1116           add_rusage (&myself->rusage_children, &child->rusage_children);
1117           add_rusage (&myself->rusage_children, &child->rusage_self);
1118
1119           if (w->rusage)
1120             {
1121               add_rusage ((struct rusage *) w->rusage, &child->rusage_children);
1122               add_rusage ((struct rusage *) w->rusage, &child->rusage_self);
1123             }
1124           ForceCloseHandle1 (child->hProcess, childhProc);
1125           child->hProcess = NULL;
1126           child->process_state = PID_NOT_IN_USE;        /* a reaped child */
1127         }
1128
1129       if (!SetEvent (w->ev))    /* wake up wait4 () immediately */
1130         system_printf ("couldn't wake up wait event %p, %E", w->ev);
1131       return 1;
1132     }
1133
1134   return -potential_match;
1135 }
1136
1137 /* Process signals by waiting for a semaphore to become signaled.
1138  * Then scan an in-memory array representing queued signals.
1139  * Executes in a separate thread.
1140  *
1141  * Signals sent from this process are sent a completion signal so
1142  * that returns from kill/raise do not occur until the signal has
1143  * has been handled, as per POSIX.
1144  */
1145 static DWORD WINAPI
1146 wait_sig (VOID *)
1147 {
1148   /* Initialization */
1149   (void) SetThreadPriority (hwait_sig, WAIT_SIG_PRIORITY);
1150
1151   /* sigcatch_nosync       - semaphore incremented by sig_dispatch_pending and
1152    *                         by foreign processes to force an examination of
1153    *                         the sigtodo array.
1154    * sigcatch_main         - ditto for local main thread.
1155    * sigcatch_nonmain      - ditto for local non-main threads.
1156    *
1157    * sigcomplete_main      - event used to signal main thread on signal
1158    *                         completion
1159    * sigcomplete_nonmain   - semaphore signaled for non-main thread on signal
1160    *                         completion
1161    */
1162   sigcatch_nosync = getsem (NULL, "sigcatch", 0, MAXLONG);
1163   sigcatch_nonmain = CreateSemaphore (&sec_none_nih, 0, MAXLONG, NULL);
1164   sigcatch_main = CreateSemaphore (&sec_none_nih, 0, MAXLONG, NULL);
1165   sigcomplete_nonmain = CreateSemaphore (&sec_none_nih, 0, MAXLONG, NULL);
1166   sigcomplete_main = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
1167   sigproc_printf ("sigcatch_nonmain %p", sigcatch_nonmain);
1168
1169   /* Setting dwProcessId flags that this process is now capable of receiving
1170    * signals.  Prior to this, dwProcessId was set to the windows pid of
1171    * of the original windows process which spawned us unless this was a
1172    * "toplevel" process.
1173    */
1174   myself->dwProcessId = GetCurrentProcessId ();
1175   myself->process_state |= PID_ACTIVE;
1176   myself->process_state &= ~PID_INITIALIZING;
1177
1178   ProtectHandle (sigcatch_nosync);
1179   ProtectHandle (sigcatch_nonmain);
1180   ProtectHandle (sigcatch_main);
1181   ProtectHandle (sigcomplete_nonmain);
1182   ProtectHandle (sigcomplete_main);
1183
1184   /* If we've been execed, then there is still a stub left in the previous
1185    * windows process waiting to see if it's started a cygwin process or not.
1186    * Signalling subproc_ready indicates that we are a cygwin process.
1187    */
1188   if (child_proc_info && child_proc_info->type == PROC_EXEC)
1189     {
1190       debug_printf ("subproc_ready %p", child_proc_info->subproc_ready);
1191       if (!SetEvent (child_proc_info->subproc_ready))
1192         system_printf ("SetEvent (subproc_ready) failed, %E");
1193       ForceCloseHandle (child_proc_info->subproc_ready);
1194     }
1195
1196   SetEvent (wait_sig_inited);
1197   sigtid = GetCurrentThreadId ();
1198
1199   /* If we got something like a SIGINT while we were initializing, the
1200      signal thread should be waiting for this event.  This signals the
1201      thread that it's ok to send the signal since the wait_sig thread
1202      is now active. */
1203   extern HANDLE console_handler_thread_waiter;
1204   SetEvent (console_handler_thread_waiter);
1205
1206   HANDLE catchem[] = {sigcatch_main, sigcatch_nonmain, sigcatch_nosync};
1207   sigproc_printf ("Ready.  dwProcessid %d", myself->dwProcessId);
1208   for (;;)
1209     {
1210       DWORD rc = WaitForMultipleObjects (3, catchem, FALSE, sig_loop_wait);
1211
1212       /* sigproc_terminate sets sig_loop_wait to zero to indicate that
1213        * this thread should terminate.
1214        */
1215       if (rc == WAIT_TIMEOUT)
1216         if (!sig_loop_wait)
1217           break;                        // Exiting
1218         else
1219           continue;
1220
1221       if (rc == WAIT_FAILED)
1222         {
1223           if (sig_loop_wait != 0)
1224             system_printf ("WFMO failed, %E");
1225           break;
1226         }
1227
1228       rc -= WAIT_OBJECT_0;
1229       int dispatched = FALSE;
1230       sigproc_printf ("awake");
1231       /* A sigcatch semaphore has been signaled.  Scan the sigtodo
1232        * array looking for any unprocessed signals.
1233        */
1234       pending_signals = 0;
1235       int saw_sigchld = 0;
1236       int dispatched_sigchld = 0;
1237       for (int sig = -__SIGOFFSET; sig < NSIG; sig++)
1238         {
1239           while (InterlockedDecrement (myself->getsigtodo(sig)) >= 0)
1240             {
1241               if (sig == SIGCHLD)
1242                 saw_sigchld = 1;
1243               if (sig > 0 && sig != SIGCONT && sig != SIGKILL && sig != SIGSTOP &&
1244                   (sigismember (& myself->getsigmask (), sig) ||
1245                    myself->process_state & PID_STOPPED))
1246                 {
1247                   sigproc_printf ("sig %d blocked", sig);
1248                   break;
1249                 }
1250
1251               /* Found a signal to process */
1252               sigproc_printf ("processing signal %d", sig);
1253               switch (sig)
1254                 {
1255                 case __SIGFLUSH:
1256                   /* just forcing the loop */
1257                   break;
1258
1259                 /* Internal signal to force a flush of strace data to disk. */
1260                 case __SIGSTRACE:
1261                   // proc_strace ();    // Dump cached strace.prntf stuff.
1262                   break;
1263
1264                 /* Signalled from a child process that it has stopped */
1265                 case __SIGCHILDSTOPPED:
1266                   sigproc_printf ("Received child stopped notification");
1267                   dispatched |= sig_handle (SIGCHLD);
1268                   if (proc_subproc (PROC_CHILDSTOPPED, 0))
1269                     dispatched |= 1;
1270                   break;
1271
1272                 /* A normal UNIX signal */
1273                 default:
1274                   sigproc_printf ("Got signal %d", sig);
1275                   int wasdispatched = sig_handle (sig);
1276                   dispatched |= wasdispatched;
1277                   if (sig == SIGCHLD && wasdispatched)
1278                     dispatched_sigchld = 1;
1279                   goto nextsig;
1280                 }
1281             }
1282           /* Decremented too far. */
1283           if (InterlockedIncrement (myself->getsigtodo(sig)) > 0)
1284             pending_signals = 1;
1285         nextsig:
1286           continue;
1287         }
1288
1289       if (saw_sigchld && !dispatched_sigchld)
1290         proc_subproc (PROC_CLEARWAIT, 0);
1291       /* Signal completion of signal handling depending on which semaphore
1292        * woke up the WaitForMultipleObjects above.
1293        */
1294       switch (rc)
1295         {
1296         case 0:
1297           SetEvent (sigcomplete_main);
1298           break;
1299         case 1:
1300           ReleaseSemaphore (sigcomplete_nonmain, 1, NULL);
1301           break;
1302         default:
1303           /* Signal from another process.  No need to synchronize. */
1304           break;
1305         }
1306
1307       if (dispatched < 0)
1308         pending_signals = 1;
1309       sigproc_printf ("looping");
1310     }
1311
1312   sigproc_printf ("done");
1313   return 0;
1314 }
1315
1316 /* Wait for subprocesses to terminate. Executes in a separate thread. */
1317 static DWORD WINAPI
1318 wait_subproc (VOID *)
1319 {
1320   sigproc_printf ("starting");
1321   int errloop = 0;
1322
1323   for (;;)
1324     {
1325       DWORD rc = WaitForMultipleObjects (nchildren + 1, events, FALSE,
1326                                          proc_loop_wait);
1327       if (rc == WAIT_TIMEOUT)
1328         if (!proc_loop_wait)
1329           break;                        // Exiting
1330         else
1331           continue;
1332
1333       if (rc == WAIT_FAILED)
1334         {
1335           if (!proc_loop_wait)
1336             break;
1337
1338           /* It's ok to get an ERROR_INVALID_HANDLE since another thread may have
1339              closed a handle in the children[] array.  So, we try looping a couple
1340              of times to stabilize. FIXME - this is not foolproof.  Probably, this
1341              thread should be responsible for closing the children. */
1342           if (++errloop < 10 && GetLastError () == ERROR_INVALID_HANDLE)
1343             continue;
1344
1345           system_printf ("wait failed. nchildren %d, wait %d, %E",
1346                         nchildren, proc_loop_wait);
1347
1348           for (int i = 0; i < nchildren + 1; i++)
1349             if ((rc = WaitForSingleObject (events[i], 0)) == WAIT_OBJECT_0 ||
1350                 rc == WAIT_TIMEOUT)
1351               continue;
1352             else
1353               system_printf ("event[%d] %p, %E", i, events[0]);
1354           break;
1355         }
1356
1357       errloop = 0;
1358       rc -= WAIT_OBJECT_0;
1359       if (rc-- != 0)
1360         (void)proc_subproc (PROC_CHILDTERMINATED, rc);
1361       sigproc_printf ("looping");
1362     }
1363
1364   ForceCloseHandle (events[0]);
1365   events[0] = NULL;
1366   sigproc_printf ("done");
1367   return 0;
1368 }
1369
1370 extern "C" {
1371 /* Provide a stack frame when calling WaitFor* functions */
1372
1373 #undef WaitForSingleObject
1374
1375 DWORD __stdcall
1376 WFSO (HANDLE hHandle, DWORD dwMilliseconds)
1377 {
1378   DWORD ret;
1379   sigframe thisframe (mainthread);
1380   ret = WaitForSingleObject (hHandle, dwMilliseconds);
1381   return ret;
1382 }
1383
1384 #undef WaitForMultipleObjects
1385
1386 DWORD __stdcall
1387 WFMO (DWORD nCount, CONST HANDLE *lpHandles, BOOL fWaitAll, DWORD dwMilliseconds)
1388 {
1389   DWORD ret;
1390   sigframe thisframe (mainthread);
1391   ret = WaitForMultipleObjects (nCount, lpHandles, fWaitAll, dwMilliseconds);
1392   return ret;
1393 }
1394 }