OSDN Git Service

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