1 /* sigproc.cc: inter/intra signal and sub process handler
3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Red Hat, Inc.
5 Written by Christopher Faylor
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
18 #include <sys/cygwin.h>
20 #include <sys/signal.h>
29 #include "child_info_magic.h"
30 #include "shared_info.h"
33 #include "exceptions.h"
38 #define WSSC 60000 // Wait for signal completion
39 #define WPSP 40000 // Wait for proc_subproc mutex
41 #define no_signals_available(x) (!my_sendsig || ((x) && myself->exitcode & EXITCODE_SET) || &_my_tls == _sig_tls)
48 struct sigaction *global_sigs;
53 char NO_COPY myself_nowait_dummy[1] = {'0'};// Flag to sig_send that signal goes to
54 // current process but no wait is required
55 HANDLE NO_COPY signal_arrived; // Event signaled when a signal has
56 // resulted in a user-specified
59 #define Static static NO_COPY
61 HANDLE NO_COPY sigCONT; // Used to "STOP" a process
63 Static HANDLE wait_sig_inited; // Control synchronization of
64 // message queue startup
66 Static int nprocs; // Number of deceased children
67 Static char cprocs[(NPROCS + 1) * sizeof (pinfo)];// All my children info
68 #define procs ((pinfo *) cprocs) // All this just to avoid expensive
69 // constructor operation at DLL startup
70 Static waitq waitq_head = {0, 0, 0, 0, 0, 0, 0};// Start of queue for wait'ing threads
72 static muto NO_COPY sync_proc_subproc; // Control access to subproc stuff
74 _cygtls NO_COPY *_sig_tls;
76 /* Function declarations */
77 static int __stdcall checkstate (waitq *) __attribute__ ((regparm (1)));
78 static __inline__ bool get_proc_lock (DWORD, DWORD);
79 static bool __stdcall remove_proc (int);
80 static bool __stdcall stopped_or_terminated (waitq *, _pinfo *);
81 static DWORD WINAPI wait_sig (VOID *arg);
82 static HANDLE NO_COPY my_sendsig;
84 /* wait_sig bookkeeping */
88 sigpacket sigs[NSIG + 1];
94 void reset () {curr = &start; prev = &start;}
95 void add (sigpacket&);
98 sigpacket *save () const {return curr;}
99 void restore (sigpacket *saved) {curr = saved;}
100 friend void __stdcall sig_dispatch_pending (bool);
101 friend DWORD WINAPI wait_sig (VOID *arg);
104 static pending_signals sigq;
110 cygheap->sigs = global_sigs =
111 (struct sigaction *) ccalloc (HEAP_SIGS, NSIG, sizeof (struct sigaction));
115 signal_fixup_after_exec ()
117 global_sigs = cygheap->sigs;
118 /* Set up child's signal handlers */
119 for (int i = 0; i < NSIG; i++)
121 global_sigs[i].sa_mask = 0;
122 if (global_sigs[i].sa_handler != SIG_IGN)
124 global_sigs[i].sa_handler = SIG_DFL;
125 global_sigs[i].sa_flags &= ~ SA_SIGINFO;
131 wait_for_sigthread ()
133 sigproc_printf ("wait_sig_inited %p", wait_sig_inited);
134 HANDLE hsig_inited = wait_sig_inited;
135 WaitForSingleObject (hsig_inited, INFINITE);
136 wait_sig_inited = NULL;
137 ForceCloseHandle1 (hsig_inited, wait_sig_inited);
140 /* Get the sync_proc_subproc muto to control access to
141 * children, proc arrays.
142 * Attempt to handle case where process is exiting as we try to grab
146 get_proc_lock (DWORD what, DWORD val)
148 Static int lastwhat = -1;
149 if (!sync_proc_subproc)
151 sigproc_printf ("sync_proc_subproc is NULL (1)");
154 if (sync_proc_subproc.acquire (WPSP))
159 if (!sync_proc_subproc)
161 sigproc_printf ("sync_proc_subproc is NULL (2)");
164 system_printf ("Couldn't aquire sync_proc_subproc for(%d,%d), last %d, %E",
165 what, val, lastwhat);
169 static bool __stdcall
170 proc_can_be_signalled (_pinfo *p)
172 if (!(p->exitcode & EXITCODE_SET))
174 if (ISSTATE (p, PID_INITIALIZING) ||
175 (((p)->process_state & (PID_ACTIVE | PID_IN_USE)) ==
176 (PID_ACTIVE | PID_IN_USE)))
185 pid_exists (pid_t pid)
187 return pinfo (pid)->exists ();
190 /* Return true if this is one of our children, false otherwise. */
191 static inline bool __stdcall
194 for (int i = 0; i < nprocs; i++)
195 if (procs[i]->pid == pid)
200 /* Handle all subprocess requests
203 proc_subproc (DWORD what, DWORD val)
211 #define wval ((waitq *) val)
212 #define vchild (*((pinfo *) val))
214 sigproc_printf ("args: %x, %d", what, val);
216 if (!get_proc_lock (what, val)) // Serialize access to this function
218 system_printf ("couldn't get proc lock. what %d, val %d", what, val);
224 /* Add a new subprocess to the children arrays.
225 * (usually called from the main thread)
228 /* Filled up process table? */
229 if (nprocs >= NPROCS)
231 sigproc_printf ("proc table overflow: hit %d processes, pid %d\n",
232 nprocs, vchild->pid);
237 /* fall through intentionally */
239 case PROC_DETACHED_CHILD:
240 if (vchild != myself)
242 vchild->ppid = what == PROC_DETACHED_CHILD ? 1 : myself->pid;
243 vchild->uid = myself->uid;
244 vchild->gid = myself->gid;
245 vchild->pgid = myself->pgid;
246 vchild->sid = myself->sid;
247 vchild->ctty = myself->ctty;
248 vchild->cygstarted = true;
249 vchild->process_state |= PID_INITIALIZING | (myself->process_state & PID_USETTY);
251 if (what == PROC_DETACHED_CHILD)
253 procs[nprocs] = vchild;
254 rc = procs[nprocs].wait ();
257 sigproc_printf ("added pid %d to proc table, slot %d", vchild->pid,
263 /* Handle a wait4() operation. Allocates an event for the calling
264 * thread which is signaled when the appropriate pid exits or stops.
265 * (usually called from the main thread)
268 wval->ev = NULL; // Don't know event flag yet
270 if (wval->pid == -1 || !wval->pid)
271 child = NULL; // Not looking for a specific pid
272 else if (!mychild (wval->pid))
273 goto out; // invalid pid. flag no such child
275 wval->status = 0; // Don't know status yet
276 sigproc_printf ("wval->pid %d, wval->options %d", wval->pid, wval->options);
278 /* If the first time for this thread, create a new event, otherwise
281 if ((wval->ev = wval->thread_ev) == NULL)
283 wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE, FALSE,
285 ProtectHandle1 (wval->ev, wq_ev);
288 ResetEvent (wval->ev);
290 waitq_head.next = wval; /* Add at the beginning. */
291 wval->next = w; /* Link in rest of the list. */
295 /* Clear all waiting threads. Called from exceptions.cc prior to
296 the main thread's dispatch to a signal handler function.
297 (called from wait_sig thread) */
299 /* Clear all "wait"ing threads. */
301 sigproc_printf ("clear waiting threads");
303 sigproc_printf ("looking for processes to reap, nprocs %d", nprocs);
307 /* Scan the linked list of wait()ing threads. If a wait's parameters
308 match this pid, then activate it. */
309 for (w = &waitq_head; w->next != NULL; w = w->next)
311 if ((potential_match = checkstate (w)) > 0)
312 sigproc_printf ("released waiting thread");
313 else if (!clearing && !(w->next->options & WNOHANG) && potential_match < 0)
314 sigproc_printf ("only found non-terminated children");
315 else if (potential_match <= 0) // nothing matched
317 sigproc_printf ("waiting thread found no children");
318 HANDLE oldw = w->next->ev;
321 w->next->status = -1; /* flag that a signal was received */
322 else if (!potential_match || !(w->next->options & WNOHANG))
324 if (!SetEvent (oldw))
325 system_printf ("couldn't wake up wait event %p, %E", oldw);
326 w->next = w->next->next;
333 sigproc_printf ("finished processing terminated/stopped child");
336 waitq_head.next = NULL;
337 sigproc_printf ("finished clearing");
340 if (global_sigs[SIGCHLD].sa_handler == (void *) SIG_IGN)
341 for (int i = 0; i < nprocs; i += remove_proc (i))
346 sync_proc_subproc.release (); // Release the lock
348 sigproc_printf ("returning %d", rc);
354 // FIXME: This is inelegant
356 _cygtls::remove_wq (DWORD wait)
358 if (sync_proc_subproc && sync_proc_subproc.acquire (wait))
360 for (waitq *w = &waitq_head; w->next != NULL; w = w->next)
363 ForceCloseHandle1 (wq.thread_ev, wq_ev);
367 sync_proc_subproc.release ();
371 /* Terminate the wait_subproc thread.
372 * Called on process exit.
373 * Also called by spawn_guts to disassociate any subprocesses from this
374 * process. Subprocesses will then know to clean up after themselves and
375 * will not become procs.
380 sigproc_printf ("nprocs %d", nprocs);
383 sync_proc_subproc.acquire (WPSP);
385 proc_subproc (PROC_CLEARWAIT, 1);
387 /* Clean out proc processes from the pid list. */
389 for (i = 0; i < nprocs; i++)
392 if (procs[i].wait_thread)
394 // CloseHandle (procs[i].rd_proc_pipe);
395 procs[i].wait_thread->terminate_thread ();
400 sync_proc_subproc.release ();
402 sigproc_printf ("leaving");
405 /* Clear pending signal */
407 sig_clear (int target_sig)
409 if (&_my_tls != _sig_tls)
410 sig_send (myself, -target_sig);
414 sigpacket *save = sigq.save ();
416 while ((q = sigq.next ()))
417 if (q->si.si_signo == target_sig)
419 q->si.si_signo = __SIGDELETE;
427 sigpending (sigset_t *mask)
429 sigset_t outset = (sigset_t) sig_send (myself, __SIGPENDING);
430 if (outset == SIG_BAD_MASK)
436 /* Force the wait_sig thread to wake up and scan for pending signals */
438 sig_dispatch_pending (bool fast)
440 if (exit_state || &_my_tls == _sig_tls || !sigq.start.next)
443 sigproc_printf ("exit_state %d, cur thread id %p, _sig_tls %p, sigq.start.next %p",
444 exit_state, GetCurrentThreadId (), _sig_tls, sigq.start.next);
450 sigproc_printf ("flushing");
452 sig_send (myself, fast ? __SIGFLUSHFAST : __SIGFLUSH);
456 create_signal_arrived ()
460 /* local event signaled when main thread has been dispatched
461 to a signal handler function. */
462 signal_arrived = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
463 ProtectHandle (signal_arrived);
466 /* Signal thread initialization. Called from dll_crt0_1.
468 This routine starts the signal handling thread. The wait_sig_inited
469 event is used to signal that the thread is ready to handle signals.
470 We don't wait for this during initialization but instead detect it
471 in sig_send to gain a little concurrency. */
475 wait_sig_inited = CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);
476 ProtectHandle (wait_sig_inited);
478 /* sync_proc_subproc is used by proc_subproc. It serialises
479 * access to the children and proc arrays.
481 sync_proc_subproc.init ("sync_proc_subproc");
483 my_sendsig = INVALID_HANDLE_VALUE; // changed later
484 cygthread *hwait_sig = new cygthread (wait_sig, 0, cygself, "sig");
487 global_sigs[SIGSTOP].sa_flags = SA_RESTART | SA_NODEFER;
488 sigproc_printf ("process/signal handling enabled, state %p", myself->process_state);
491 /* Called on process termination to terminate signal and process threads.
494 sigproc_terminate (exit_states es)
496 exit_states prior_exit_state = exit_state;
498 if (prior_exit_state >= ES_FINAL)
499 sigproc_printf ("already performed");
502 sigproc_printf ("entering");
503 sig_send (myself_nowait, __SIGEXIT);
504 proc_terminate (); // clean up process stuff
509 sig_send (_pinfo *p, int sig)
513 si.si_code = SI_KERNEL;
514 si.si_pid = si.si_uid = si.si_errno = 0;
515 return sig_send (p, si);
518 /* Send a signal to another process by raising its signal semaphore.
519 If pinfo *p == NULL, send to the current process.
520 If sending to this process, wait for notification that a signal has
521 completed before returning. */
523 sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
529 bool communing = si.si_signo == __SIGCOMMUNE;
532 bool wait_for_completion;
533 if (!(its_me = (p == NULL || p == myself || p == myself_nowait)))
535 /* It is possible that the process is not yet ready to receive messages
536 * or that it has exited. Detect this.
538 if (!proc_can_be_signalled (p)) /* Is the process accepting messages? */
540 sigproc_printf ("invalid pid %d(%x), signal %d",
541 p->pid, p->process_state, si.si_signo);
544 wait_for_completion = false;
548 if (no_signals_available (si.si_signo != __SIGEXIT))
550 sigproc_printf ("my_sendsig %p, myself->sendsig %p, exit_state %d",
551 my_sendsig, myself->sendsig, exit_state);
553 goto out; // Either exiting or not yet initializing
556 wait_for_sigthread ();
557 wait_for_completion = p != myself_nowait && _my_tls.isinitialized () && !exit_state;
563 sendsig = my_sendsig;
568 for (int i = 0; !p->sendsig && i < 10000; i++)
569 low_priority_sleep (0);
573 dwProcessId = p->dwProcessId;
577 dupsig = p->exec_sendsig;
578 dwProcessId = p->exec_dwProcessId;
583 sigproc_printf ("sendsig handle never materialized");
586 HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId);
590 sigproc_printf ("OpenProcess failed, %E");
594 if (!DuplicateHandle (hp, dupsig, hMainProc, &sendsig, false, 0,
595 DUPLICATE_SAME_ACCESS) || !sendsig)
598 sigproc_printf ("DuplicateHandle failed, %E");
602 VerifyHandle (sendsig);
607 si._si_commune._si_process_handle = hp;
609 HANDLE& tome = si._si_commune._si_write_handle;
610 HANDLE& fromthem = si._si_commune._si_read_handle;
611 if (!CreatePipe (&fromthem, &tome, &sec_all_nih, 0))
613 sigproc_printf ("CreatePipe for __SIGCOMMUNE failed, %E");
617 if (!DuplicateHandle (hMainProc, tome, hp, &tome, false, 0,
618 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
620 sigproc_printf ("DuplicateHandle for __SIGCOMMUNE failed, %E");
627 sigproc_printf ("sendsig %p, pid %d, signal %d, its_me %d", sendsig, p->pid, si.si_signo, its_me);
632 else if (si.si_signo == __SIGPENDING)
633 pack.mask = &pending;
634 else if (si.si_signo == __SIGFLUSH || si.si_signo > 0)
635 pack.mask = &myself->getsigmask ();
641 pack.si.si_pid = myself->pid;
643 pack.si.si_uid = myself->uid;
644 pack.pid = myself->pid;
645 pack.tls = (_cygtls *) tls;
646 if (wait_for_completion)
648 pack.wakeup = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
649 sigproc_printf ("wakeup %p", pack.wakeup);
650 ProtectHandle (pack.wakeup);
655 if (!communing || !(si._si_commune._si_code & PICOM_EXTRASTR))
657 leader = (char *) &pack;
658 packsize = sizeof (pack);
662 size_t n = strlen (si._si_commune._si_str);
663 char *p = leader = (char *) alloca (sizeof (pack) + sizeof (n) + n);
664 memcpy (p, &pack, sizeof (pack)); p += sizeof (pack);
665 memcpy (p, &n, sizeof (n)); p += sizeof (n);
666 memcpy (p, si._si_commune._si_str, n); p += n;
667 packsize = p - leader;
671 if (!WriteFile (sendsig, leader, packsize, &nb, NULL) || nb != packsize)
673 /* Couldn't send to the pipe. This probably means that the
674 process is exiting. */
678 sigproc_printf ("WriteFile for pipe %p failed, %E", sendsig);
679 ForceCloseHandle (sendsig);
683 if (no_signals_available (true))
684 sigproc_printf ("I'm going away now");
685 else if (!p->exec_sendsig)
686 system_printf ("error sending signal %d to pid %d, pipe handle %p, %E",
687 si.si_signo, p->pid, sendsig);
694 /* No need to wait for signal completion unless this was a signal to
697 If it was a signal to this process, wait for a dispatched signal.
698 Otherwise just wait for the wait_sig to signal that it has finished
699 processing the signal. */
700 if (wait_for_completion)
702 sigproc_printf ("Waiting for pack.wakeup %p", pack.wakeup);
703 rc = WaitForSingleObject (pack.wakeup, WSSC);
704 ForceCloseHandle (pack.wakeup);
709 sigproc_printf ("Not waiting for sigcomplete. its_me %d signal %d",
710 its_me, si.si_signo);
712 ForceCloseHandle (sendsig);
716 if (rc == WAIT_OBJECT_0)
717 rc = 0; // Successful exit
720 if (!no_signals_available (true))
721 system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E",
727 if (wait_for_completion && si.si_signo != __SIGFLUSHFAST)
728 _my_tls.call_signal_handler ();
734 if (si._si_commune._si_process_handle)
735 CloseHandle (si._si_commune._si_process_handle);
736 if (si._si_commune._si_read_handle)
737 CloseHandle (si._si_commune._si_read_handle);
740 ForceCloseHandle (pack.wakeup);
741 if (si.si_signo != __SIGPENDING)
747 sigproc_printf ("returning %p from sending signal %d", rc, si.si_signo);
751 /* Initialize some of the memory block passed to child processes
752 by fork/spawn/exec. */
754 child_info::child_info (unsigned in_cb, child_info_types chtype, bool need_subproc_ready)
756 memset (this, 0, in_cb);
758 intro = PROC_MAGIC_GENERIC;
759 magic = CHILD_INFO_MAGIC;
761 fhandler_union_cb = sizeof (fhandler_union);
762 user_h = cygwin_user_h;
763 if (need_subproc_ready)
764 subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
765 sigproc_printf ("subproc_ready %p", subproc_ready);
767 cygheap_max = ::cygheap_max;
768 dwProcessId = myself->dwProcessId;
769 /* Create an inheritable handle to pass to the child process. This will
770 allow the child to duplicate handles from the parent to itself. */
772 if (!DuplicateHandle (hMainProc, hMainProc, hMainProc, &parent, 0, TRUE,
773 DUPLICATE_SAME_ACCESS))
774 system_printf ("couldn't create handle to myself for child, %E");
777 child_info::~child_info ()
780 CloseHandle (subproc_ready);
782 CloseHandle (parent);
785 child_info_fork::child_info_fork () :
786 child_info (sizeof *this, _PROC_FORK, true)
790 child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_ready) :
791 child_info (sizeof *this, chtype, need_subproc_ready)
796 child_info::ready (bool execed)
800 sigproc_printf ("subproc_ready not set");
804 if (dynamically_loaded)
805 sigproc_printf ("not really ready");
806 else if (!SetEvent (subproc_ready))
807 api_fatal ("SetEvent failed");
809 sigproc_printf ("signalled %p that I was ready", subproc_ready);
813 CloseHandle (subproc_ready);
814 subproc_ready = NULL;
819 child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong)
824 unsigned nsubproc_ready;
827 nsubproc_ready = WAIT_OBJECT_0 + 3;
830 w4[n++] = subproc_ready;
835 sigproc_printf ("n %d, waiting for subproc_ready(%p) and child process(%p)", n, w4[0], w4[1]);
836 DWORD x = WaitForMultipleObjects (n, w4, FALSE, howlong);
840 system_printf ("wait failed, pid %d, %E", pid);
845 if (type == _PROC_EXEC && x == nsubproc_ready && myself->wr_proc_pipe)
847 ForceCloseHandle1 (hProcess, childhProcess);
850 sigproc_printf ("process %d synchronized, WFMO returned %d", pid, x);
856 /* Check the state of all of our children to see if any are stopped or
860 checkstate (waitq *parent_w)
862 int potential_match = 0;
864 sigproc_printf ("nprocs %d", nprocs);
866 /* Check already dead processes first to see if they match the criteria
867 * given in w->next. */
869 for (int i = 0; i < nprocs; i++)
870 if ((res = stopped_or_terminated (parent_w, procs[i])))
877 sigproc_printf ("no matching terminated children found");
878 potential_match = -!!nprocs;
881 sigproc_printf ("returning %d", potential_match);
882 return potential_match;
885 /* Remove a proc from procs by swapping it with the last child in the list.
886 Also releases shared memory of exited processes. */
887 static bool __stdcall
890 if (procs[ci]->exists ())
893 sigproc_printf ("removing procs[%d], pid %d, nprocs %d", ci, procs[ci]->pid,
895 if (procs[ci] != myself)
897 procs[ci].release ();
898 if (procs[ci].hProcess)
899 ForceCloseHandle1 (procs[ci].hProcess, childhProc);
903 /* Wait for proc_waiter thread to make a copy of this element before
904 moving it or it may become confused. The chances are very high that
905 the proc_waiter thread has already done this by the time we
907 while (!procs[nprocs].waiter_ready)
908 low_priority_sleep (0);
909 procs[ci] = procs[nprocs];
914 /* Check status of child process vs. waitq member.
916 parent_w is the pointer to the parent of the waitq member in question.
917 child is the subprocess being considered.
919 Returns non-zero if waiting thread released. */
920 static bool __stdcall
921 stopped_or_terminated (waitq *parent_w, _pinfo *child)
924 waitq *w = parent_w->next;
926 sigproc_printf ("considering pid %d", child->pid);
929 else if (w->pid == 0)
930 might_match = child->pgid == myself->pgid;
932 might_match = child->pgid == -w->pid;
934 might_match = (w->pid == child->pid);
941 if (!((terminated = (child->process_state == PID_EXITED)) ||
942 ((w->options & WUNTRACED) && child->stopsig)))
945 parent_w->next = w->next; /* successful wait. remove from wait queue */
950 sigproc_printf ("stopped child");
951 w->status = (child->stopsig << 8) | 0x7f;
956 w->status = (__uint16_t) child->exitcode;
958 add_rusage (&myself->rusage_children, &child->rusage_children);
959 add_rusage (&myself->rusage_children, &child->rusage_self);
963 add_rusage ((struct rusage *) w->rusage, &child->rusage_children);
964 add_rusage ((struct rusage *) w->rusage, &child->rusage_self);
968 if (!SetEvent (w->ev)) /* wake up wait4 () immediately */
969 system_printf ("couldn't wake up wait event %p, %E", w->ev);
974 talktome (siginfo_t *si, HANDLE readsig)
976 unsigned size = sizeof (*si);
977 sigproc_printf ("pid %d wants some information", si->si_pid);
978 if (si->_si_commune._si_code & PICOM_EXTRASTR)
982 if (!ReadFile (readsig, &n, sizeof (n), &nb, NULL) || nb != sizeof (n))
984 siginfo_t *newsi = (siginfo_t *) alloca (size += n + 1);
986 newsi->_si_commune._si_str = (char *) (newsi + 1);
987 if (!ReadFile (readsig, newsi->_si_commune._si_str, n, &nb, NULL) || nb != n)
989 newsi->_si_commune._si_str[n] = '\0';
993 pinfo pi (si->si_pid);
995 new cygthread (commune_process, size, si, "commune_process");
999 pending_signals::add (sigpacket& pack)
1002 if (sigs[pack.si.si_signo].si.si_signo)
1004 se = sigs + pack.si.si_signo;
1006 se->mask = &myself->getsigmask ();
1016 pending_signals::del ()
1018 sigpacket *next = curr->next;
1020 curr->si.si_signo = 0;
1030 pending_signals::next ()
1034 if (!curr || !(curr = curr->next))
1041 /* Process signals by waiting for signal data to arrive in a pipe.
1042 Set a completion event if one was specified. */
1047 PSECURITY_ATTRIBUTES sa_buf = (PSECURITY_ATTRIBUTES) alloca (1024);
1048 Static bool holding_signals;
1050 /* Initialization */
1051 SetThreadPriority (GetCurrentThread (), WAIT_SIG_PRIORITY);
1053 if (!CreatePipe (&readsig, &myself->sendsig, sec_user_nih (sa_buf), 0))
1054 api_fatal ("couldn't create signal pipe, %E");
1055 ProtectHandle (readsig);
1056 sigCONT = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
1057 my_sendsig = myself->sendsig;
1059 /* Setting dwProcessId flags that this process is now capable of receiving
1060 signals. Prior to this, dwProcessId was set to the windows pid of
1061 of the original windows process which spawned us unless this was a
1062 "toplevel" process. */
1063 myself->process_state |= PID_ACTIVE;
1064 myself->process_state &= ~PID_INITIALIZING;
1066 _sig_tls = &_my_tls;
1067 sigproc_printf ("myself->dwProcessId %u", myself->dwProcessId);
1068 SetEvent (wait_sig_inited);
1071 _sig_tls->init_threadlist_exceptions (&el);
1072 debug_printf ("entering ReadFile loop, readsig %p, myself->sendsig %p",
1073 readsig, myself->sendsig);
1080 if (!ReadFile (readsig, &pack, sizeof (pack), &nb, NULL))
1083 if (nb != sizeof (pack))
1085 system_printf ("short read from signal pipe: %d != %d", nb,
1090 if (!pack.si.si_signo)
1093 system_printf ("zero signal?");
1098 sigset_t dummy_mask;
1101 dummy_mask = myself->getsigmask ();
1102 pack.mask = &dummy_mask;
1106 bool clearwait = false;
1107 switch (pack.si.si_signo)
1110 talktome (&pack.si, readsig);
1119 while ((q = sigq.next ()))
1120 if (myself->getsigmask () & (bit = SIGTOMASK (q->si.si_signo)))
1124 holding_signals = 1;
1127 holding_signals = 0;
1128 /* fall through, intentionally */
1130 case __SIGFLUSHFAST:
1132 while ((q = sigq.next ()))
1134 int sig = q->si.si_signo;
1135 if (sig == __SIGDELETE || q->process () > 0)
1137 if (sig == __SIGNOHOLD && q->si.si_signo == SIGCHLD)
1142 sigproc_printf ("saw __SIGEXIT");
1143 break; /* handle below */
1145 if (pack.si.si_signo < 0)
1146 sig_clear (-pack.si.si_signo);
1147 else if (holding_signals)
1151 int sig = pack.si.si_signo;
1152 // FIXME: REALLY not right when taking threads into consideration.
1153 // We need a per-thread queue since each thread can have its own
1154 // list of blocked signals. CGF 2005-08-24
1155 if (sigq.sigs[sig].si.si_signo && sigq.sigs[sig].tls == pack.tls)
1156 sigproc_printf ("sig %d already queued", pack.si.si_signo);
1159 int sigres = pack.process ();
1164 system_printf ("Failed to arm signal %d from pid %d", pack.sig, pack.pid);
1166 sigq.add (pack); // FIXME: Shouldn't add this in !sh condition
1175 proc_subproc (PROC_CLEARWAIT, 0);
1178 SetEvent (pack.wakeup);
1179 sigproc_printf ("signalled %p", pack.wakeup);
1181 if (pack.si.si_signo == __SIGEXIT)
1185 ForceCloseHandle (readsig);
1186 sigproc_printf ("signal thread exiting");