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