]> sourceware.org Git - newlib-cygwin.git/blame_incremental - winsup/cygwin/sigproc.cc
Cygwin: add release message for latest pipe changes
[newlib-cygwin.git] / winsup / cygwin / sigproc.cc
... / ...
CommitLineData
1/* sigproc.cc: inter/intra signal and sub process handler
2
3This file is part of Cygwin.
4
5This software is a copyrighted work licensed under the terms of the
6Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7details. */
8
9#include "winsup.h"
10#include "miscfuncs.h"
11#include <stdlib.h>
12#include <sys/cygwin.h>
13#include "cygerrno.h"
14#include "sigproc.h"
15#include "path.h"
16#include "fhandler.h"
17#include "dtable.h"
18#include "cygheap.h"
19#include "child_info_magic.h"
20#include "shared_info.h"
21#include "cygtls.h"
22#include "ntdll.h"
23#include "exception.h"
24
25/*
26 * Convenience defines
27 */
28#define WSSC 60000 // Wait for signal completion
29#define WPSP 40000 // Wait for proc_subproc mutex
30
31/*
32 * Global variables
33 */
34struct sigaction *global_sigs;
35
36const char *__sp_fn ;
37int __sp_ln;
38
39bool no_thread_exit_protect::flag;
40
41/* Flag to sig_send that signal goes to current process but no wait is
42 required. */
43char NO_COPY myself_nowait_dummy[1] = {'0'};
44
45/* All my children info. Avoid expensive constructor ops at DLL
46 startup.
47
48 This class can allocate memory. But there's no need to free it
49 because only one instance of the class is created per process. */
50class child_procs {
51 static const int _NPROCS = 1024;
52 static const int _NPROCS_2 = 4095;
53 int _count;
54 uint8_t _procs[_NPROCS * sizeof (pinfo)] __attribute__ ((__aligned__));
55 pinfo *_procs_2;
56 public:
57 int count () const { return _count; }
58 int add_one () { return ++_count; }
59 int del_one () { return --_count; }
60 int reset () { return _count = 0; }
61 pinfo &operator[] (int idx)
62 {
63 if (idx >= _NPROCS)
64 {
65 if (!_procs_2)
66 {
67 /* Use HeapAlloc to avoid propagating this memory area
68 to the child processes. */
69 _procs_2 = (pinfo *) HeapAlloc (GetProcessHeap (),
70 HEAP_GENERATE_EXCEPTIONS
71 | HEAP_ZERO_MEMORY,
72 (_NPROCS_2 + 1) * sizeof (pinfo));
73 }
74 return _procs_2[idx - _NPROCS];
75 }
76 return ((pinfo *) _procs)[idx];
77 }
78 int max_child_procs () const { return _NPROCS + _NPROCS_2; }
79};
80static NO_COPY child_procs chld_procs;
81
82/* Start of queue for waiting threads. */
83static NO_COPY waitq waitq_head;
84
85/* Controls access to subproc stuff. */
86static NO_COPY muto sync_proc_subproc;
87
88_cygtls NO_COPY *_sig_tls;
89
90static NO_COPY HANDLE my_sendsig;
91static NO_COPY HANDLE my_readsig;
92
93/* Used in select if a signalfd is part of the read descriptor set */
94HANDLE NO_COPY my_pendingsigs_evt;
95
96/* Function declarations */
97static int checkstate (waitq *);
98static __inline__ bool get_proc_lock (DWORD, DWORD);
99static int remove_proc (int);
100static bool stopped_or_terminated (waitq *, _pinfo *);
101static void wait_sig (VOID *arg);
102
103/* wait_sig bookkeeping */
104
105class pending_signals
106{
107 sigpacket sigs[_NSIG + 1];
108 sigpacket start;
109 bool retry;
110
111public:
112 void add (sigpacket&);
113 bool pending () {retry = true; return !!start.next;}
114 void clear (int sig) {sigs[sig].si.si_signo = 0;}
115 void clear (_cygtls *tls);
116 friend void sig_dispatch_pending (bool);
117 friend void wait_sig (VOID *arg);
118};
119
120static NO_COPY pending_signals sigq;
121
122/* Functions */
123void
124sigalloc ()
125{
126 cygheap->sigs = global_sigs =
127 (struct sigaction *) ccalloc_abort (HEAP_SIGS, _NSIG, sizeof (struct sigaction));
128 global_sigs[SIGSTOP].sa_flags = SA_RESTART | SA_NODEFER;
129}
130
131void
132signal_fixup_after_exec ()
133{
134 global_sigs = cygheap->sigs;
135 /* Set up child's signal handlers */
136 for (int i = 0; i < _NSIG; i++)
137 {
138 global_sigs[i].sa_mask = 0;
139 if (global_sigs[i].sa_handler != SIG_IGN)
140 {
141 global_sigs[i].sa_handler = SIG_DFL;
142 global_sigs[i].sa_flags &= ~ SA_SIGINFO;
143 }
144 }
145}
146
147/* Get the sync_proc_subproc muto to control access to
148 * children, proc arrays.
149 * Attempt to handle case where process is exiting as we try to grab
150 * the mutex.
151 */
152static bool
153get_proc_lock (DWORD what, DWORD val)
154{
155 if (!cygwin_finished_initializing)
156 return true;
157 static NO_COPY int lastwhat = -1;
158 if (!sync_proc_subproc)
159 {
160 sigproc_printf ("sync_proc_subproc is NULL");
161 return false;
162 }
163 if (sync_proc_subproc.acquire (WPSP))
164 {
165 lastwhat = what;
166 return true;
167 }
168 system_printf ("Couldn't acquire %s for(%d,%d), last %d, %E",
169 sync_proc_subproc.name, what, val, lastwhat);
170 return false;
171}
172
173static bool
174proc_can_be_signalled (_pinfo *p)
175{
176 if (!(p->exitcode & EXITCODE_SET))
177 {
178 if (ISSTATE (p, PID_INITIALIZING) ||
179 (((p)->process_state & (PID_ACTIVE | PID_IN_USE)) ==
180 (PID_ACTIVE | PID_IN_USE)))
181 return true;
182 }
183
184 set_errno (ESRCH);
185 return false;
186}
187
188bool
189pid_exists (pid_t pid)
190{
191 pinfo p (pid);
192 return p && p->exists ();
193}
194
195/* Return true if this is one of our children, false otherwise. */
196static inline bool
197mychild (int pid)
198{
199 for (int i = 0; i < chld_procs.count (); i++)
200 if (chld_procs[i]->pid == pid)
201 return true;
202 return false;
203}
204
205/* Handle all subprocess requests
206 */
207int
208proc_subproc (DWORD what, uintptr_t val)
209{
210 int slot;
211 int rc = 1;
212 int potential_match;
213 int clearing;
214 waitq *w;
215
216#define wval ((waitq *) val)
217#define vchild (*((pinfo *) val))
218
219 sigproc_printf ("args: %x, %d", what, val);
220
221 if (!get_proc_lock (what, val)) // Serialize access to this function
222 {
223 system_printf ("couldn't get proc lock. what %d, val %d", what, val);
224 goto out1;
225 }
226
227 switch (what)
228 {
229 /* Add a new subprocess to the children arrays.
230 * (usually called from the main thread)
231 */
232 case PROC_ADD_CHILD:
233 /* Filled up process table? */
234 if (chld_procs.count () >= chld_procs.max_child_procs ())
235 {
236 sigproc_printf ("proc table overflow: hit %d processes, pid %d\n",
237 chld_procs.count (), vchild->pid);
238 rc = 0;
239 set_errno (EAGAIN);
240 break;
241 }
242
243 if (vchild != myself)
244 {
245 vchild->uid = myself->uid;
246 vchild->gid = myself->gid;
247 vchild->pgid = myself->pgid;
248 vchild->sid = myself->sid;
249 vchild->ctty = myself->ctty;
250 vchild->cygstarted = true;
251 vchild->process_state |= PID_INITIALIZING;
252 vchild->ppid = myself->pid; /* always set last */
253 }
254 break;
255
256 case PROC_ATTACH_CHILD:
257 slot = chld_procs.count ();
258 chld_procs[slot] = vchild;
259 rc = chld_procs[slot].wait ();
260 if (rc)
261 {
262 sigproc_printf ("added pid %d to proc table, slot %d", vchild->pid,
263 slot);
264 chld_procs.add_one ();
265 }
266 break;
267
268 /* Handle a wait4() operation. Allocates an event for the calling
269 * thread which is signaled when the appropriate pid exits or stops.
270 * (usually called from the main thread)
271 */
272 case PROC_WAIT:
273 wval->ev = NULL; // Don't know event flag yet
274
275 if (wval->pid != -1 && wval->pid && !mychild (wval->pid))
276 goto out; // invalid pid. flag no such child
277
278 wval->status = 0; // Don't know status yet
279 sigproc_printf ("wval->pid %d, wval->options %d", wval->pid, wval->options);
280
281 /* If the first time for this thread, create a new event, otherwise
282 * reset the event.
283 */
284 if ((wval->ev = wval->thread_ev) == NULL)
285 {
286 wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE, FALSE,
287 NULL);
288 ProtectHandle1 (wval->ev, wq_ev);
289 }
290
291 ResetEvent (wval->ev);
292 w = waitq_head.next;
293 waitq_head.next = wval; /* Add at the beginning. */
294 wval->next = w; /* Link in rest of the list. */
295 clearing = false;
296 goto scan_wait;
297
298 case PROC_EXEC_CLEANUP:
299 /* Cleanup backwards to eliminate redundant copying of chld_procs
300 array members inside remove_proc. */
301 while (chld_procs.count ())
302 remove_proc (chld_procs.count () - 1);
303 for (w = &waitq_head; w->next != NULL; w = w->next)
304 CloseHandle (w->next->ev);
305 break;
306
307 /* Clear all waiting threads. Called from exceptions.cc prior to
308 the main thread's dispatch to a signal handler function.
309 (called from wait_sig thread) */
310 case PROC_CLEARWAIT:
311 /* Clear all "wait"ing threads. */
312 if (val)
313 sigproc_printf ("clear waiting threads");
314 else
315 sigproc_printf ("looking for processes to reap, count %d",
316 chld_procs.count ());
317 clearing = val;
318
319 scan_wait:
320 /* Scan the linked list of wait()ing threads. If a wait's parameters
321 match this pid, then activate it. */
322 for (w = &waitq_head; w->next != NULL; w = w->next)
323 {
324 if ((potential_match = checkstate (w)) > 0)
325 sigproc_printf ("released waiting thread");
326 else if (!clearing && !(w->next->options & WNOHANG) && potential_match < 0)
327 sigproc_printf ("only found non-terminated children");
328 else if (potential_match <= 0) // nothing matched
329 {
330 sigproc_printf ("waiting thread found no children");
331 HANDLE oldw = w->next->ev;
332 w->next->pid = 0;
333 if (clearing)
334 w->next->status = -1; /* flag that a signal was received */
335 else if (!potential_match || !(w->next->options & WNOHANG))
336 w->next->ev = NULL;
337 if (!SetEvent (oldw))
338 system_printf ("couldn't wake up wait event %p, %E", oldw);
339 w->next = w->next->next;
340 }
341 if (w->next == NULL)
342 break;
343 }
344
345 if (!clearing)
346 sigproc_printf ("finished processing terminated/stopped child");
347 else
348 {
349 waitq_head.next = NULL;
350 sigproc_printf ("finished clearing");
351 }
352
353 if (global_sigs[SIGCHLD].sa_handler == (void *) SIG_IGN)
354 for (int i = 0; i < chld_procs.count (); i += remove_proc (i))
355 continue;
356 }
357
358out:
359 sync_proc_subproc.release (); // Release the lock
360out1:
361 sigproc_printf ("returning %d", rc);
362 return rc;
363#undef wval
364#undef vchild
365}
366
367// FIXME: This is inelegant
368void
369_cygtls::remove_wq (DWORD wait)
370{
371 if (wq.thread_ev)
372 {
373 if (exit_state < ES_FINAL && waitq_head.next && sync_proc_subproc
374 && sync_proc_subproc.acquire (wait))
375 {
376 ForceCloseHandle1 (wq.thread_ev, wq_ev);
377 wq.thread_ev = NULL;
378 for (waitq *w = &waitq_head; w->next != NULL; w = w->next)
379 if (w->next == &wq)
380 {
381 w->next = wq.next;
382 break;
383 }
384 sync_proc_subproc.release ();
385 }
386 }
387
388}
389
390/* Terminate the wait_subproc thread.
391 Called on process exit.
392 Also called by spawn_guts to disassociate any subprocesses from this
393 process. Subprocesses will then know to clean up after themselves and
394 will not become chld_procs. */
395void
396proc_terminate ()
397{
398 sigproc_printf ("child_procs count %d", chld_procs.count ());
399 if (chld_procs.count ())
400 {
401 sync_proc_subproc.acquire (WPSP);
402
403 proc_subproc (PROC_CLEARWAIT, 1);
404
405 /* Clean out proc processes from the pid list. */
406 for (int i = 0; i < chld_procs.count (); i++)
407 {
408 /* If we've execed then the execed process will handle setting ppid
409 to 1 iff it is a Cygwin process. */
410 if (!have_execed || !have_execed_cygwin)
411 chld_procs[i]->ppid = 1;
412 if (chld_procs[i].wait_thread)
413 chld_procs[i].wait_thread->terminate_thread ();
414 /* Release memory associated with this process unless it is 'myself'.
415 'myself' is only in the chld_procs table when we've execed. We
416 reach here when the next process has finished initializing but we
417 still can't free the memory used by 'myself' since it is used
418 later on during cygwin tear down. */
419 if (chld_procs[i] != myself)
420 chld_procs[i].release ();
421 }
422 chld_procs.reset ();
423 sync_proc_subproc.release ();
424 }
425 sigproc_printf ("leaving");
426}
427
428/* Clear pending signal */
429void
430sig_clear (int sig)
431{
432 sigq.clear (sig);
433}
434
435/* Clear pending signals of specific thread. Called under TLS lock from
436 _cygtls::remove_pending_sigs. */
437void
438pending_signals::clear (_cygtls *tls)
439{
440 sigpacket *q = &start, *qnext;
441
442 while ((qnext = q->next))
443 if (qnext->sigtls == tls)
444 {
445 qnext->si.si_signo = 0;
446 q->next = qnext->next;
447 }
448 else
449 q = qnext;
450}
451
452/* Clear pending signals of specific thread. Called from _cygtls::remove */
453void
454_cygtls::remove_pending_sigs ()
455{
456 sigq.clear (this);
457}
458
459extern "C" int
460sigpending (sigset_t *mask)
461{
462 sigset_t outset = sig_send (myself, __SIGPENDING, &_my_tls);
463 if (outset == SIG_BAD_MASK)
464 return -1;
465 *mask = outset;
466 return 0;
467}
468
469/* Force the wait_sig thread to wake up and scan for pending signals */
470void
471sig_dispatch_pending (bool fast)
472{
473 /* Non-atomically test for any signals pending and wake up wait_sig if any are
474 found. It's ok if there's a race here since the next call to this function
475 should catch it. */
476 if (sigq.pending () && &_my_tls != _sig_tls)
477 sig_send (myself, fast ? __SIGFLUSHFAST : __SIGFLUSH);
478}
479
480/* Signal thread initialization. Called from dll_crt0_1.
481 This routine starts the signal handling thread. */
482void
483sigproc_init ()
484{
485 char char_sa_buf[1024];
486 PSECURITY_ATTRIBUTES sa = sec_user_nih ((PSECURITY_ATTRIBUTES) char_sa_buf, cygheap->user.sid());
487 DWORD err = fhandler_pipe::create (sa, &my_readsig, &my_sendsig,
488 _NSIG * sizeof (sigpacket), "sigwait",
489 PIPE_ADD_PID);
490 if (err)
491 {
492 SetLastError (err);
493 api_fatal ("couldn't create signal pipe, %E");
494 }
495 ProtectHandle (my_readsig);
496 myself->sendsig = my_sendsig;
497 my_pendingsigs_evt = CreateEvent (NULL, TRUE, FALSE, NULL);
498 if (!my_pendingsigs_evt)
499 api_fatal ("couldn't create pending signal event, %E");
500
501 /* sync_proc_subproc is used by proc_subproc. It serializes
502 access to the children and proc arrays. */
503 sync_proc_subproc.init ("sync_proc_subproc");
504 new cygthread (wait_sig, cygself, "sig");
505}
506
507/* Exit the current thread very carefully.
508 See cgf-000017 in DevNotes for more details on why this is
509 necessary. */
510void
511exit_thread (DWORD res)
512{
513# undef ExitThread
514 if (no_thread_exit_protect ())
515 ExitThread (res);
516 sigfillset (&_my_tls.sigmask); /* No signals wanted */
517
518 /* CV 2014-11-21: Disable the code sending a signal. The problem with
519 this code is that it allows deadlocks under signal-rich multithreading
520 conditions.
521 The original problem reported in 2012 couldn't be reproduced anymore,
522 even disabling this code. Tested on XP 32, Vista 32, W7 32, WOW64, 64,
523 W8.1 WOW64, 64. */
524#if 0
525 lock_process for_now; /* May block indefinitely when exiting. */
526 HANDLE h;
527 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
528 GetCurrentProcess (), &h,
529 0, FALSE, DUPLICATE_SAME_ACCESS))
530 {
531#ifdef DEBUGGING
532 system_printf ("couldn't duplicate the current thread, %E");
533#endif
534 for_now.release ();
535 ExitThread (res);
536 }
537 ProtectHandle1 (h, exit_thread);
538 /* Tell wait_sig to wait for this thread to exit. It can then release
539 the lock below and close the above-opened handle. */
540 siginfo_t si = {__SIGTHREADEXIT, SI_KERNEL};
541 si.si_cyg = h;
542 sig_send (myself_nowait, si, &_my_tls);
543#endif
544 ExitThread (res);
545}
546
547sigset_t
548sig_send (_pinfo *p, int sig, _cygtls *tls)
549{
550 siginfo_t si = {};
551 si.si_signo = sig;
552 si.si_code = SI_KERNEL;
553 return sig_send (p, si, tls);
554}
555
556/* Send a signal to another process by raising its signal semaphore.
557 If pinfo *p == NULL, send to the current process.
558 If sending to this process, wait for notification that a signal has
559 completed before returning. */
560sigset_t
561sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
562{
563 int rc = 1;
564 bool its_me;
565 HANDLE sendsig;
566 sigpacket pack;
567 bool communing = si.si_signo == __SIGCOMMUNE;
568
569 pack.wakeup = NULL;
570 bool wait_for_completion;
571 if (!(its_me = p == NULL || p == myself || p == myself_nowait))
572 {
573 /* It is possible that the process is not yet ready to receive messages
574 * or that it has exited. Detect this.
575 */
576 if (!proc_can_be_signalled (p)) /* Is the process accepting messages? */
577 {
578 sigproc_printf ("invalid pid %d(%x), signal %d",
579 p->pid, p->process_state, si.si_signo);
580 goto out;
581 }
582 wait_for_completion = false;
583 }
584 else
585 {
586 wait_for_completion = p != myself_nowait;
587 p = myself;
588 }
589
590 /* If myself is the stub process, send signal to the child process
591 rather than myself. The fact that myself->dwProcessId is not equal
592 to the current process id indicates myself is the stub process. */
593 if (its_me && myself->dwProcessId != GetCurrentProcessId ())
594 {
595 wait_for_completion = false;
596 its_me = false;
597 }
598
599 if (its_me)
600 sendsig = my_sendsig;
601 else
602 {
603 HANDLE dupsig;
604 DWORD dwProcessId;
605 for (int i = 0; !p->sendsig && i < 10000; i++)
606 yield ();
607 if (p->sendsig)
608 {
609 dupsig = p->sendsig;
610 dwProcessId = p->dwProcessId;
611 }
612 else
613 {
614 dupsig = p->exec_sendsig;
615 dwProcessId = p->exec_dwProcessId;
616 }
617 if (!dupsig)
618 {
619 set_errno (EAGAIN);
620 sigproc_printf ("sendsig handle never materialized");
621 goto out;
622 }
623 HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId);
624 if (!hp)
625 {
626 __seterrno ();
627 sigproc_printf ("OpenProcess failed, %E");
628 goto out;
629 }
630 VerifyHandle (hp);
631 if (!DuplicateHandle (hp, dupsig, GetCurrentProcess (), &sendsig, 0,
632 false, DUPLICATE_SAME_ACCESS) || !sendsig)
633 {
634 __seterrno ();
635 sigproc_printf ("DuplicateHandle failed, %E");
636 CloseHandle (hp);
637 goto out;
638 }
639 VerifyHandle (sendsig);
640 if (!communing)
641 {
642 CloseHandle (hp);
643 DWORD flag = PIPE_NOWAIT;
644 /* Set PIPE_NOWAIT here to avoid blocking when sending a signal.
645 (Yes, I know MSDN says not to use this)
646 We can't ever block here because it causes a deadlock when
647 debugging with gdb. */
648 BOOL res = SetNamedPipeHandleState (sendsig, &flag, NULL, NULL);
649 sigproc_printf ("%d = SetNamedPipeHandleState (%y, PIPE_NOWAIT, NULL, NULL)", res, sendsig);
650 }
651 else
652 {
653 si._si_commune._si_process_handle = hp;
654
655 HANDLE& tome = si._si_commune._si_write_handle;
656 HANDLE& fromthem = si._si_commune._si_read_handle;
657 if (!CreatePipeOverlapped (&fromthem, &tome, &sec_all_nih))
658 {
659 sigproc_printf ("CreatePipe for __SIGCOMMUNE failed, %E");
660 __seterrno ();
661 goto out;
662 }
663 if (!DuplicateHandle (GetCurrentProcess (), tome, hp, &tome, 0, false,
664 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
665 {
666 sigproc_printf ("DuplicateHandle for __SIGCOMMUNE failed, %E");
667 __seterrno ();
668 goto out;
669 }
670 }
671 }
672
673 sigproc_printf ("sendsig %p, pid %d, signal %d, its_me %d", sendsig, p->pid,
674 si.si_signo, its_me);
675
676 sigset_t pending;
677 if (!its_me)
678 pack.mask = NULL;
679 else if (si.si_signo == __SIGPENDING || si.si_signo == __SIGPENDINGALL)
680 pack.mask = &pending;
681 else if (si.si_signo == __SIGFLUSH || si.si_signo > 0)
682 {
683 threadlist_t *tl_entry = cygheap->find_tls (tls ? tls : _main_tls);
684 pack.mask = tls ? &tls->sigmask : &_main_tls->sigmask;
685 cygheap->unlock_tls (tl_entry);
686 }
687 else
688 pack.mask = NULL;
689
690 pack.si = si;
691 if (!pack.si.si_pid)
692 pack.si.si_pid = myself->pid;
693 if (!pack.si.si_uid)
694 pack.si.si_uid = myself->uid;
695 pack.pid = myself->pid;
696 pack.sigtls = tls;
697 if (wait_for_completion)
698 {
699 pack.wakeup = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
700 sigproc_printf ("wakeup %p", pack.wakeup);
701 ProtectHandle (pack.wakeup);
702 }
703
704 char *leader;
705 size_t packsize;
706 if (!communing || !(si._si_commune._si_code & PICOM_EXTRASTR))
707 {
708 leader = (char *) &pack;
709 packsize = sizeof (pack);
710 }
711 else
712 {
713 size_t n = strlen (si._si_commune._si_str);
714 packsize = sizeof (pack) + sizeof (n) + n;
715 char *p = leader = (char *) alloca (packsize);
716 memcpy (p, &pack, sizeof (pack)); p += sizeof (pack);
717 memcpy (p, &n, sizeof (n)); p += sizeof (n);
718 memcpy (p, si._si_commune._si_str, n); p += n;
719 }
720
721 DWORD nb;
722 BOOL res;
723 /* Try multiple times to send if packsize != nb since that probably
724 means that the pipe buffer is full. */
725 for (int i = 0; i < 100; i++)
726 {
727 res = WriteFile (sendsig, leader, packsize, &nb, NULL);
728 if (!res || packsize == nb)
729 break;
730 Sleep (10);
731 res = 0;
732 }
733
734 if (!res)
735 {
736 /* Couldn't send to the pipe. This probably means that the
737 process is exiting. */
738 if (!its_me)
739 {
740 sigproc_printf ("WriteFile for pipe %p failed, %E", sendsig);
741 ForceCloseHandle (sendsig);
742 }
743 else if (!p->exec_sendsig && !exit_state)
744 system_printf ("error sending signal %d, pid %u, pipe handle %p, nb %u, packsize %u, %E",
745 si.si_signo, p->pid, sendsig, nb, packsize);
746 if (GetLastError () == ERROR_BROKEN_PIPE)
747 set_errno (ESRCH);
748 else
749 __seterrno ();
750 goto out;
751 }
752
753
754 /* No need to wait for signal completion unless this was a signal to
755 this process.
756
757 If it was a signal to this process, wait for a dispatched signal.
758 Otherwise just wait for the wait_sig to signal that it has finished
759 processing the signal. */
760 if (wait_for_completion)
761 {
762 sigproc_printf ("Waiting for pack.wakeup %p", pack.wakeup);
763 rc = WaitForSingleObject (pack.wakeup, WSSC);
764 ForceCloseHandle (pack.wakeup);
765 }
766 else
767 {
768 rc = WAIT_OBJECT_0;
769 sigproc_printf ("Not waiting for sigcomplete. its_me %d signal %d",
770 its_me, si.si_signo);
771 if (!its_me)
772 ForceCloseHandle (sendsig);
773 }
774
775 pack.wakeup = NULL;
776 if (rc == WAIT_OBJECT_0)
777 rc = 0; // Successful exit
778 else
779 {
780 set_errno (ENOSYS);
781 rc = -1;
782 }
783
784 if (wait_for_completion && si.si_signo != __SIGFLUSHFAST)
785 _my_tls.call_signal_handler ();
786
787out:
788 if (communing && rc)
789 {
790 if (si._si_commune._si_process_handle)
791 CloseHandle (si._si_commune._si_process_handle);
792 if (si._si_commune._si_read_handle)
793 CloseHandle (si._si_commune._si_read_handle);
794 }
795 if (pack.wakeup)
796 ForceCloseHandle (pack.wakeup);
797 if (si.si_signo != __SIGPENDING && si.si_signo != __SIGPENDINGALL)
798 /* nothing */;
799 else if (!rc)
800 rc = pending;
801 else
802 rc = SIG_BAD_MASK;
803 sigproc_printf ("returning %p from sending signal %d", rc, si.si_signo);
804 return rc;
805}
806
807int child_info::retry_count = 0;
808
809/* Initialize some of the memory block passed to child processes
810 by fork/spawn/exec. */
811child_info::child_info (unsigned in_cb, child_info_types chtype,
812 bool need_subproc_ready):
813 msv_count (0), cb (in_cb), intro (PROC_MAGIC_GENERIC),
814 magic (CHILD_INFO_MAGIC), type (chtype), cygheap (::cygheap),
815 cygheap_max (::cygheap_max), flag (0), retry (child_info::retry_count),
816 rd_proc_pipe (NULL), wr_proc_pipe (NULL), sigmask (_my_tls.sigmask)
817{
818 fhandler_union_cb = sizeof (fhandler_union);
819 user_h = cygwin_user_h;
820 if (strace.active ())
821 {
822 NTSTATUS status;
823 ULONG DebugFlags;
824
825 /* Only propagate _CI_STRACED to child if strace is actually tracing
826 child processes of this process. The undocumented ProcessDebugFlags
827 returns 0 if EPROCESS->NoDebugInherit is TRUE, 1 otherwise.
828 This avoids a hang when stracing a forking or spawning process
829 with the -f flag set to "don't follow fork". */
830 status = NtQueryInformationProcess (GetCurrentProcess (),
831 ProcessDebugFlags, &DebugFlags,
832 sizeof (DebugFlags), NULL);
833 if (NT_SUCCESS (status) && DebugFlags)
834 flag |= _CI_STRACED;
835 }
836 if (need_subproc_ready)
837 {
838 subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
839 flag |= _CI_ISCYGWIN;
840 }
841 sigproc_printf ("subproc_ready %p", subproc_ready);
842 /* Create an inheritable handle to pass to the child process. This will
843 allow the child to copy cygheap etc. from the parent to itself. If
844 we're forking, we also need handle duplicate access. */
845 parent = NULL;
846 DWORD perms = PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ
847 | PROCESS_VM_OPERATION | SYNCHRONIZE;
848 if (type == _CH_FORK)
849 perms |= PROCESS_DUP_HANDLE;
850
851 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
852 GetCurrentProcess (), &parent, perms, TRUE, 0))
853 system_printf ("couldn't create handle to myself for child, %E");
854}
855
856child_info::~child_info ()
857{
858 cleanup ();
859}
860
861child_info_fork::child_info_fork () :
862 child_info (sizeof *this, _CH_FORK, true),
863 forker_finished (NULL)
864{
865}
866
867child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_ready) :
868 child_info (sizeof *this, chtype, need_subproc_ready)
869{
870 if (type == _CH_EXEC)
871 {
872 hExeced = NULL;
873 if (my_wr_proc_pipe)
874 ev = NULL;
875 else if (!(ev = CreateEvent (&sec_none_nih, false, false, NULL)))
876 api_fatal ("couldn't create signalling event for exec, %E");
877
878 get_proc_lock (PROC_EXECING, 0);
879 /* exit with lock held */
880 }
881}
882
883cygheap_exec_info *
884cygheap_exec_info::alloc ()
885{
886 cygheap_exec_info *res =
887 (cygheap_exec_info *) ccalloc_abort (HEAP_1_EXEC, 1,
888 sizeof (cygheap_exec_info)
889 + (chld_procs.count ()
890 * sizeof (children[0])));
891 return res;
892}
893
894void
895child_info_spawn::wait_for_myself ()
896{
897 postfork (myself);
898 if (myself.remember ())
899 myself.attach ();
900 WaitForSingleObject (ev, INFINITE);
901}
902
903void
904child_info::cleanup ()
905{
906 if (subproc_ready)
907 {
908 CloseHandle (subproc_ready);
909 subproc_ready = NULL;
910 }
911 if (parent)
912 {
913 CloseHandle (parent);
914 parent = NULL;
915 }
916 if (rd_proc_pipe)
917 {
918 ForceCloseHandle (rd_proc_pipe);
919 rd_proc_pipe = NULL;
920 }
921 if (wr_proc_pipe)
922 {
923 ForceCloseHandle (wr_proc_pipe);
924 wr_proc_pipe = NULL;
925 }
926}
927
928void
929child_info_spawn::cleanup ()
930{
931 if (moreinfo)
932 {
933 if (moreinfo->envp)
934 {
935 for (char **e = moreinfo->envp; *e; e++)
936 cfree (*e);
937 cfree (moreinfo->envp);
938 }
939 if (type != _CH_SPAWN && moreinfo->myself_pinfo)
940 CloseHandle (moreinfo->myself_pinfo);
941 cfree (moreinfo);
942 }
943 moreinfo = NULL;
944 if (ev)
945 {
946 CloseHandle (ev);
947 ev = NULL;
948 }
949 if (type == _CH_EXEC)
950 {
951 if (iscygwin () && hExeced)
952 proc_subproc (PROC_EXEC_CLEANUP, 0);
953 sync_proc_subproc.release ();
954 }
955 type = _CH_NADA;
956 child_info::cleanup ();
957}
958
959/* Record any non-reaped subprocesses to be passed to about-to-be-execed
960 process. FIXME: There is a race here if the process exits while we
961 are recording it. */
962inline void
963cygheap_exec_info::record_children ()
964{
965 for (nchildren = 0; nchildren < chld_procs.count (); nchildren++)
966 {
967 children[nchildren].pid = chld_procs[nchildren]->pid;
968 children[nchildren].p = chld_procs[nchildren];
969 /* Set inheritance of required child handles for reattach_children
970 in the about-to-be-execed process. */
971 children[nchildren].p.set_inheritance (true);
972 }
973}
974
975void
976child_info_spawn::record_children ()
977{
978 if (type == _CH_EXEC && iscygwin ())
979 moreinfo->record_children ();
980}
981
982/* Reattach non-reaped subprocesses passed in from the cygwin process
983 which previously operated under this pid. FIXME: Is there a race here
984 if the process exits during cygwin's exec handoff? */
985inline void
986cygheap_exec_info::reattach_children (HANDLE parent)
987{
988 for (int i = 0; i < nchildren; i++)
989 {
990 pinfo p (parent, children[i].p, children[i].pid);
991 if (!p)
992 debug_only_printf ("couldn't reattach child %d from previous process", children[i].pid);
993 else if (!p.attach ())
994 debug_only_printf ("attach of child process %d failed", children[i].pid);
995 else
996 debug_only_printf ("reattached pid %d<%u>, process handle %p, rd_proc_pipe %p->%p",
997 p->pid, p->dwProcessId, p.hProcess,
998 children[i].p.rd_proc_pipe, p.rd_proc_pipe);
999 }
1000}
1001
1002void
1003child_info_spawn::reattach_children ()
1004{
1005 moreinfo->reattach_children (parent);
1006}
1007
1008void
1009child_info::ready (bool execed)
1010{
1011 if (!subproc_ready)
1012 {
1013 sigproc_printf ("subproc_ready not set");
1014 return;
1015 }
1016
1017 if (dynamically_loaded)
1018 sigproc_printf ("not really ready");
1019 else if (!SetEvent (subproc_ready))
1020 api_fatal ("SetEvent failed, %E");
1021 else
1022 sigproc_printf ("signalled %p that I was ready", subproc_ready);
1023
1024 if (execed)
1025 {
1026 CloseHandle (subproc_ready);
1027 subproc_ready = NULL;
1028 }
1029}
1030
1031bool
1032child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong)
1033{
1034 bool res;
1035 HANDLE w4[2];
1036 unsigned n = 0;
1037 unsigned nsubproc_ready;
1038
1039 if (!subproc_ready)
1040 nsubproc_ready = WAIT_OBJECT_0 + 3;
1041 else
1042 {
1043 w4[n++] = subproc_ready;
1044 nsubproc_ready = 0;
1045 }
1046 w4[n++] = hProcess;
1047
1048 sigproc_printf ("n %d, waiting for subproc_ready(%p) and child process(%p)", n, w4[0], w4[1]);
1049 DWORD x = WaitForMultipleObjects (n, w4, FALSE, howlong);
1050 x -= WAIT_OBJECT_0;
1051 if (x >= n)
1052 {
1053 system_printf ("wait failed, pid %u, %E", pid);
1054 res = false;
1055 }
1056 else
1057 {
1058 if (x != nsubproc_ready)
1059 {
1060 res = false;
1061 GetExitCodeProcess (hProcess, &exit_code);
1062 }
1063 else
1064 {
1065 res = true;
1066 exit_code = STILL_ACTIVE;
1067 if (type == _CH_EXEC && my_wr_proc_pipe)
1068 {
1069 ForceCloseHandle1 (hProcess, childhProc);
1070 hProcess = NULL;
1071 }
1072 }
1073 sigproc_printf ("pid %u, WFMO returned %d, exit_code %y, res %d", pid, x,
1074 exit_code, res);
1075 }
1076 return res;
1077}
1078
1079DWORD
1080child_info::proc_retry (HANDLE h)
1081{
1082 if (!exit_code)
1083 return EXITCODE_OK;
1084 sigproc_printf ("exit_code %y", exit_code);
1085 switch ((NTSTATUS) exit_code)
1086 {
1087 case STILL_ACTIVE: /* shouldn't happen */
1088 sigproc_printf ("STILL_ACTIVE? How'd we get here?");
1089 break;
1090 case STATUS_DLL_NOT_FOUND:
1091 case STATUS_ACCESS_VIOLATION:
1092 case STATUS_ILLEGAL_INSTRUCTION:
1093 case STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION: /* pseudo-reloc.c specific */
1094 return exit_code;
1095 case STATUS_CONTROL_C_EXIT:
1096 if (saw_ctrl_c ())
1097 return EXITCODE_OK;
1098 fallthrough;
1099 case STATUS_DLL_INIT_FAILED:
1100 case STATUS_DLL_INIT_FAILED_LOGOFF:
1101 case EXITCODE_RETRY:
1102 if (retry-- > 0)
1103 exit_code = 0;
1104 break;
1105 case EXITCODE_FORK_FAILED: /* windows prevented us from forking */
1106 break;
1107
1108 /* Count down non-recognized exit codes more quickly since they aren't
1109 due to known conditions. */
1110 default:
1111 if (!iscygwin () && (exit_code & 0xffff0000) != 0xc0000000)
1112 break;
1113 if ((retry -= 2) < 0)
1114 retry = 0;
1115 else
1116 exit_code = 0;
1117 }
1118 if (!exit_code)
1119 ForceCloseHandle1 (h, childhProc);
1120 return exit_code;
1121}
1122
1123bool
1124child_info_fork::abort (const char *fmt, ...)
1125{
1126 if (fmt)
1127 {
1128 va_list ap;
1129 va_start (ap, fmt);
1130 if (silentfail ())
1131 strace_vprintf (DEBUG, fmt, ap);
1132 else
1133 strace_vprintf (SYSTEM, fmt, ap);
1134 TerminateProcess (GetCurrentProcess (), EXITCODE_FORK_FAILED);
1135 }
1136 if (retry > 0)
1137 TerminateProcess (GetCurrentProcess (), EXITCODE_RETRY);
1138 return false;
1139}
1140
1141/* Check the state of all of our children to see if any are stopped or
1142 * terminated.
1143 */
1144static int
1145checkstate (waitq *parent_w)
1146{
1147 int potential_match = 0;
1148
1149 sigproc_printf ("child_procs count %d", chld_procs.count ());
1150
1151 /* Check already dead processes first to see if they match the criteria
1152 * given in w->next. */
1153 int res;
1154 for (int i = 0; i < chld_procs.count (); i++)
1155 if ((res = stopped_or_terminated (parent_w, chld_procs[i])))
1156 {
1157 remove_proc (i);
1158 potential_match = 1;
1159 goto out;
1160 }
1161
1162 sigproc_printf ("no matching terminated children found");
1163 potential_match = -!!chld_procs.count ();
1164
1165out:
1166 sigproc_printf ("returning %d", potential_match);
1167 return potential_match;
1168}
1169
1170/* Remove a proc from chld_procs by swapping it with the last child in the list.
1171 Also releases shared memory of exited processes. */
1172static int
1173remove_proc (int ci)
1174{
1175 if (have_execed)
1176 {
1177 if (_my_tls._ctinfo != chld_procs[ci].wait_thread)
1178 chld_procs[ci].wait_thread->terminate_thread ();
1179 }
1180 else if (chld_procs[ci] && chld_procs[ci]->exists ())
1181 return 1;
1182
1183 sigproc_printf ("removing chld_procs[%d], pid %d, child_procs count %d",
1184 ci, chld_procs[ci]->pid, chld_procs.count ());
1185 if (chld_procs[ci] != myself)
1186 chld_procs[ci].release ();
1187 if (ci < chld_procs.del_one ())
1188 {
1189 /* Wait for proc_waiter thread to make a copy of this element before
1190 moving it or it may become confused. The chances are very high that
1191 the proc_waiter thread has already done this by the time we
1192 get here. */
1193 if (!have_execed && !exit_state)
1194 while (!chld_procs[chld_procs.count ()].waiter_ready)
1195 yield ();
1196 chld_procs[ci] = chld_procs[chld_procs.count ()];
1197 }
1198 return 0;
1199}
1200
1201/* Check status of child process vs. waitq member.
1202
1203 parent_w is the pointer to the parent of the waitq member in question.
1204 child is the subprocess being considered.
1205
1206 Returns non-zero if waiting thread released. */
1207static bool
1208stopped_or_terminated (waitq *parent_w, _pinfo *child)
1209{
1210 int might_match;
1211 waitq *w = parent_w->next;
1212
1213 sigproc_printf ("considering pid %d, pgid %d, w->pid %d", child->pid, child->pgid, w->pid);
1214 if (w->pid == -1)
1215 might_match = 1;
1216 else if (w->pid == 0)
1217 might_match = child->pgid == myself->pgid;
1218 else if (w->pid < 0)
1219 might_match = child->pgid == -w->pid;
1220 else
1221 might_match = (w->pid == child->pid);
1222
1223 if (!might_match)
1224 return false;
1225
1226 int terminated;
1227
1228 if (!((terminated = (child->process_state == PID_EXITED))
1229 || ((w->options & WCONTINUED) && child->stopsig == SIGCONT)
1230 || ((w->options & WUNTRACED) && child->stopsig && child->stopsig != SIGCONT)))
1231 return false;
1232
1233 parent_w->next = w->next; /* successful wait. remove from wait queue */
1234 w->pid = child->pid;
1235
1236 if (!terminated)
1237 {
1238 sigproc_printf ("stopped child, stop signal %d", child->stopsig);
1239 if (child->stopsig == SIGCONT)
1240 w->status = __W_CONTINUED;
1241 else
1242 w->status = (child->stopsig << 8) | 0x7f;
1243 child->stopsig = 0;
1244 }
1245 else
1246 {
1247 child->process_state = PID_REAPED;
1248 w->status = (__uint16_t) child->exitcode;
1249
1250 add_rusage (&myself->rusage_children, &child->rusage_children);
1251 add_rusage (&myself->rusage_children, &child->rusage_self);
1252
1253 if (w->rusage)
1254 {
1255 add_rusage ((struct rusage *) w->rusage, &child->rusage_children);
1256 add_rusage ((struct rusage *) w->rusage, &child->rusage_self);
1257 }
1258 }
1259
1260 if (!SetEvent (w->ev)) /* wake up wait4 () immediately */
1261 system_printf ("couldn't wake up wait event %p, %E", w->ev);
1262 return true;
1263}
1264
1265static void
1266talktome (siginfo_t *si)
1267{
1268 unsigned size = sizeof (*si);
1269 sigproc_printf ("pid %d wants some information", si->si_pid);
1270 if (si->_si_commune._si_code & PICOM_EXTRASTR)
1271 {
1272 size_t n;
1273 DWORD nb;
1274 if (!ReadFile (my_readsig, &n, sizeof (n), &nb, NULL) || nb != sizeof (n))
1275 return;
1276 siginfo_t *newsi = (siginfo_t *) alloca (size += n + 1);
1277 *newsi = *si;
1278 newsi->_si_commune._si_str = (char *) (newsi + 1);
1279 if (!ReadFile (my_readsig, newsi->_si_commune._si_str, n, &nb, NULL) || nb != n)
1280 return;
1281 newsi->_si_commune._si_str[n] = '\0';
1282 si = newsi;
1283 }
1284
1285 pinfo pi (si->si_pid);
1286 if (pi)
1287 new cygthread (commune_process, size, si, "commune");
1288}
1289
1290/* Add a packet to the beginning of the queue.
1291 Should only be called from signal thread. */
1292void
1293pending_signals::add (sigpacket& pack)
1294{
1295 sigpacket *se;
1296
1297 se = sigs + pack.si.si_signo;
1298 if (se->si.si_signo)
1299 return;
1300 *se = pack;
1301 se->next = start.next;
1302 start.next = se;
1303}
1304
1305/* Process signals by waiting for signal data to arrive in a pipe.
1306 Set a completion event if one was specified. */
1307static void
1308wait_sig (VOID *)
1309{
1310 _sig_tls = &_my_tls;
1311 bool sig_held = false;
1312
1313 sigproc_printf ("entering ReadFile loop, my_readsig %p, my_sendsig %p",
1314 my_readsig, my_sendsig);
1315
1316 hntdll = GetModuleHandle ("ntdll.dll");
1317
1318 for (;;)
1319 {
1320 DWORD nb;
1321 sigpacket pack = {};
1322 if (sigq.retry)
1323 pack.si.si_signo = __SIGFLUSH;
1324 else if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL))
1325 Sleep (INFINITE); /* Assume were exiting. Never exit this thread */
1326 else if (nb != sizeof (pack) || !pack.si.si_signo)
1327 {
1328 system_printf ("garbled signal pipe data nb %u, sig %d", nb, pack.si.si_signo);
1329 continue;
1330 }
1331
1332 sigq.retry = false;
1333 /* Don't process signals when we start exiting */
1334 if (exit_state > ES_EXIT_STARTING && pack.si.si_signo > 0)
1335 goto skip_process_signal;
1336
1337 sigset_t dummy_mask;
1338 threadlist_t *tl_entry;
1339 if (!pack.mask)
1340 {
1341 /* There's a short time at process startup of a forked process,
1342 when _main_tls points to the system-allocated stack, not to
1343 the parent thread. In that case find_tls fails, and we fetch
1344 the sigmask from the child_info passed from the parent. */
1345 if (cygwin_finished_initializing)
1346 {
1347 tl_entry = cygheap->find_tls (_main_tls);
1348 dummy_mask = _main_tls->sigmask;
1349 cygheap->unlock_tls (tl_entry);
1350 }
1351 else if (child_proc_info)
1352 dummy_mask = child_proc_info->sigmask;
1353 else
1354 dummy_mask = 0;
1355 pack.mask = &dummy_mask;
1356 }
1357
1358 sigpacket *q;
1359 q = &sigq.start;
1360 bool clearwait;
1361 clearwait = false;
1362 switch (pack.si.si_signo)
1363 {
1364 case __SIGCOMMUNE:
1365 talktome (&pack.si);
1366 break;
1367 case __SIGSTRACE:
1368 strace.activate (false);
1369 break;
1370 case __SIGPENDINGALL:
1371 {
1372 unsigned bit;
1373 bool issig_wait;
1374
1375 *pack.mask = 0;
1376 while ((q = q->next))
1377 {
1378 _cygtls *sigtls = q->sigtls ?: _main_tls;
1379 if (sigtls->sigmask & (bit = SIGTOMASK (q->si.si_signo)))
1380 {
1381 tl_entry = cygheap->find_tls (q->si.si_signo, issig_wait);
1382 if (tl_entry)
1383 {
1384 *pack.mask |= bit;
1385 cygheap->unlock_tls (tl_entry);
1386 }
1387 }
1388 }
1389 }
1390 break;
1391 case __SIGPENDING:
1392 {
1393 unsigned bit;
1394
1395 *pack.mask = 0;
1396 tl_entry = cygheap->find_tls (pack.sigtls);
1397 while ((q = q->next))
1398 {
1399 /* Skip thread-specific signals for other threads. */
1400 if (q->sigtls && pack.sigtls != q->sigtls)
1401 continue;
1402 if (pack.sigtls->sigmask & (bit = SIGTOMASK (q->si.si_signo)))
1403 *pack.mask |= bit;
1404 }
1405 cygheap->unlock_tls (tl_entry);
1406 }
1407 break;
1408 case __SIGHOLD:
1409 sig_held = true;
1410 break;
1411 case __SIGSETPGRP:
1412 init_console_handler (::cygheap->ctty
1413 && ::cygheap->ctty->is_console ());
1414 break;
1415 case __SIGTHREADEXIT:
1416 {
1417 /* Serialize thread exit as the thread exit code can be interpreted
1418 as the process exit code in some cases when racing with
1419 ExitProcess/TerminateProcess.
1420 So, wait for the thread which sent this signal to exit, then
1421 release the process lock which it held and close it's handle.
1422 See cgf-000017 in DevNotes for more details.
1423 */
1424 HANDLE h = (HANDLE) pack.si.si_cyg;
1425 DWORD res = WaitForSingleObject (h, 5000);
1426 lock_process::force_release (pack.sigtls);
1427 ForceCloseHandle1 (h, exit_thread);
1428 if (res != WAIT_OBJECT_0)
1429 {
1430#ifdef DEBUGGING
1431 try_to_debug();
1432#endif
1433 system_printf ("WaitForSingleObject(%p) for thread exit returned %u", h, res);
1434 }
1435 }
1436 break;
1437 default: /* Normal (positive) signal */
1438 if (pack.si.si_signo < 0)
1439 sig_clear (-pack.si.si_signo);
1440 else
1441 sigq.add (pack);
1442 fallthrough;
1443 case __SIGNOHOLD:
1444 sig_held = false;
1445 fallthrough;
1446 case __SIGFLUSH:
1447 case __SIGFLUSHFAST:
1448 if (!sig_held)
1449 {
1450 sigpacket *qnext;
1451 /* Check the queue for signals. There will always be at least one
1452 thing on the queue if this was a valid signal. */
1453 while ((qnext = q->next))
1454 {
1455 if (qnext->si.si_signo && qnext->process () <= 0)
1456 q = qnext;
1457 else
1458 {
1459 q->next = qnext->next;
1460 qnext->si.si_signo = 0;
1461 }
1462 }
1463 /* At least one signal still queued? The event is used in select
1464 only, and only to decide if WFMO should wake up in case a
1465 signalfd is waiting via select/poll for being ready to read a
1466 pending signal. This method wakes up all threads hanging in
1467 select and having a signalfd, as soon as a pending signal is
1468 available, but it's certainly better than constant polling. */
1469 if (sigq.start.next)
1470 SetEvent (my_pendingsigs_evt);
1471 else
1472 ResetEvent (my_pendingsigs_evt);
1473 if (pack.si.si_signo == SIGCHLD)
1474 clearwait = true;
1475 }
1476 break;
1477 case __SIGNONCYGCHLD:
1478 cygheap_fdenum cfd (false);
1479 while (cfd.next () >= 0)
1480 if (cfd->get_dev () == FH_PIPEW)
1481 {
1482 fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
1483 if (pipe->need_close_query_hdl ())
1484 pipe->close_query_handle ();
1485 }
1486 break;
1487 }
1488 if (clearwait && !have_execed)
1489 proc_subproc (PROC_CLEARWAIT, 0);
1490skip_process_signal:
1491 if (pack.wakeup)
1492 {
1493 sigproc_printf ("signalling pack.wakeup %p", pack.wakeup);
1494 SetEvent (pack.wakeup);
1495 }
1496 }
1497}
This page took 0.03293 seconds and 6 git commands to generate.