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