]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/sigproc.cc
* DevNotes: Add entry cgf-000013.
[newlib-cygwin.git] / winsup / cygwin / sigproc.cc
CommitLineData
1fd5e000
CF
1/* sigproc.cc: inter/intra signal and sub process handler
2
68f62c98 3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
0e1f0840 4 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
1fd5e000
CF
5
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
4c8d72de 12#include "winsup.h"
ade47a34 13#include "miscfuncs.h"
1fd5e000 14#include <stdlib.h>
f0338f54 15#include <sys/cygwin.h>
9e2baf8d 16#include "cygerrno.h"
0e1f0840 17#include "sigproc.h"
47063f00 18#include "path.h"
7ac61736 19#include "fhandler.h"
0381fec6 20#include "dtable.h"
8dec7b03 21#include "cygheap.h"
77f4a250 22#include "child_info_magic.h"
29ac7f89 23#include "shared_info.h"
62e070d7 24#include "cygtls.h"
93d606f6 25#include "ntdll.h"
e52a43f1 26#include "exception.h"
1fd5e000
CF
27
28/*
29 * Convenience defines
30 */
b50fe821
CF
31#define WSSC 60000 // Wait for signal completion
32#define WPSP 40000 // Wait for proc_subproc mutex
33
6c6eb02b 34#define no_signals_available(x) (!my_sendsig || ((x) && myself->exitcode & EXITCODE_SET) || (&_my_tls == _sig_tls))
1fd5e000
CF
35
36/*
37 * Global variables
38 */
474048c2
CF
39struct sigaction *global_sigs;
40
1fd5e000
CF
41const char *__sp_fn ;
42int __sp_ln;
43
44char NO_COPY myself_nowait_dummy[1] = {'0'};// Flag to sig_send that signal goes to
45 // current process but no wait is required
1fd5e000 46
edc4f86a 47#define Static static NO_COPY
1fd5e000 48
0428827b 49HANDLE NO_COPY sigCONT; // Used to "STOP" a process
1fd5e000 50
e8bf2329 51Static bool sigheld; // True if holding signals
1fd5e000 52
8cb359d9 53Static int nprocs; // Number of deceased children
37d5841f
CF
54Static 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
6b838263 57Static waitq waitq_head; // Start of queue for wait'ing threads
1fd5e000 58
e8bf2329 59Static muto sync_proc_subproc; // Control access to subproc stuff
f02f1f14 60
a611ae50 61_cygtls NO_COPY *_sig_tls;
1fd5e000 62
81010d21 63Static HANDLE my_sendsig;
4ab568c6 64Static HANDLE my_readsig;
81010d21 65
474048c2 66/* Function declarations */
99a8fab5 67static int __stdcall checkstate (waitq *) __attribute__ ((regparm (1)));
2e008fb9 68static __inline__ bool get_proc_lock (DWORD, DWORD);
8cb359d9
CF
69static bool __stdcall remove_proc (int);
70static bool __stdcall stopped_or_terminated (waitq *, _pinfo *);
b9874a0c 71static void WINAPI wait_sig (VOID *arg);
1fd5e000 72
474048c2
CF
73/* wait_sig bookkeeping */
74
75class pending_signals
76{
77 sigpacket sigs[NSIG + 1];
78 sigpacket start;
79 sigpacket *end;
80 sigpacket *prev;
81 sigpacket *curr;
82public:
83 void reset () {curr = &start; prev = &start;}
84 void add (sigpacket&);
85 void del ();
dc3dc498 86 bool pending () const {return !!start.next;}
474048c2
CF
87 sigpacket *next ();
88 sigpacket *save () const {return curr;}
89 void restore (sigpacket *saved) {curr = saved;}
90 friend void __stdcall sig_dispatch_pending (bool);
b9874a0c 91 friend void WINAPI wait_sig (VOID *arg);
474048c2
CF
92};
93
e8bf2329 94Static pending_signals sigq;
474048c2
CF
95
96/* Functions */
edc4f86a
CF
97void __stdcall
98sigalloc ()
99{
100 cygheap->sigs = global_sigs =
ee4388c4 101 (struct sigaction *) ccalloc_abort (HEAP_SIGS, NSIG, sizeof (struct sigaction));
bbca1e4c 102 global_sigs[SIGSTOP].sa_flags = SA_RESTART | SA_NODEFER;
edc4f86a
CF
103}
104
105void __stdcall
106signal_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)
d5f4ee62
CF
114 {
115 global_sigs[i].sa_handler = SIG_DFL;
116 global_sigs[i].sa_flags &= ~ SA_SIGINFO;
117 }
edc4f86a
CF
118 }
119}
120
243a041b 121/* Get the sync_proc_subproc muto to control access to
8cb359d9 122 * children, proc arrays.
243a041b
CF
123 * Attempt to handle case where process is exiting as we try to grab
124 * the mutex.
125 */
2e008fb9 126static bool
243a041b
CF
127get_proc_lock (DWORD what, DWORD val)
128{
b79b15e9
CF
129 if (!cygwin_finished_initializing)
130 return true;
243a041b
CF
131 Static int lastwhat = -1;
132 if (!sync_proc_subproc)
76832a5b 133 {
26bb3098 134 sigproc_printf ("sync_proc_subproc is NULL");
76832a5b
CF
135 return false;
136 }
322c131f 137 if (sync_proc_subproc.acquire (WPSP))
243a041b
CF
138 {
139 lastwhat = what;
2e008fb9 140 return true;
243a041b 141 }
26bb3098
CF
142 system_printf ("Couldn't acquire %s for(%d,%d), last %d, %E",
143 sync_proc_subproc.name, what, val, lastwhat);
144 return false;
243a041b
CF
145}
146
2e008fb9 147static bool __stdcall
84c7d409 148proc_can_be_signalled (_pinfo *p)
1fd5e000 149{
67483cb2 150 if (!(p->exitcode & EXITCODE_SET))
1ed95be6 151 {
8232f2e0
CF
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 }
1ed95be6
CF
157
158 set_errno (ESRCH);
159 return false;
1fd5e000
CF
160}
161
2e008fb9 162bool __stdcall
488c7683 163pid_exists (pid_t pid)
84c7d409 164{
1a9a235a 165 return pinfo (pid)->exists ();
84c7d409
CF
166}
167
54dd79bb
CF
168/* Return true if this is one of our children, false otherwise. */
169static inline bool __stdcall
0ef78625
CF
170mychild (int pid)
171{
54dd79bb
CF
172 for (int i = 0; i < nprocs; i++)
173 if (procs[i]->pid == pid)
174 return true;
175 return false;
0ef78625
CF
176}
177
1fd5e000
CF
178/* Handle all subprocess requests
179 */
1fd5e000
CF
180int __stdcall
181proc_subproc (DWORD what, DWORD val)
182{
183 int rc = 1;
184 int potential_match;
84c7d409 185 _pinfo *child;
9aa07a8f 186 int clearing;
1fd5e000
CF
187 waitq *w;
188
189#define wval ((waitq *) val)
54dd79bb 190#define vchild (*((pinfo *) val))
1fd5e000 191
a5a965ff 192 sigproc_printf ("args: %x, %d", what, val);
1fd5e000
CF
193
194 if (!get_proc_lock (what, val)) // Serialize access to this function
195 {
76832a5b 196 system_printf ("couldn't get proc lock. what %d, val %d", what, val);
1fd5e000
CF
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:
8cb359d9
CF
206 /* Filled up process table? */
207 if (nprocs >= NPROCS)
cde0c2fb 208 {
8cb359d9
CF
209 sigproc_printf ("proc table overflow: hit %d processes, pid %d\n",
210 nprocs, vchild->pid);
cde0c2fb 211 rc = 0;
54dd79bb 212 set_errno (EAGAIN);
cde0c2fb
CF
213 break;
214 }
4ee52924 215 /* fall through intentionally */
8cb359d9 216
4ee52924 217 case PROC_DETACHED_CHILD:
54dd79bb
CF
218 if (vchild != myself)
219 {
6e3c97b1 220 vchild->ppid = what == PROC_DETACHED_CHILD ? 1 : myself->pid;
54dd79bb
CF
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;
c75b5b2d 227 vchild->process_state |= PID_INITIALIZING;
54dd79bb 228 }
4ee52924
CF
229 if (what == PROC_DETACHED_CHILD)
230 break;
b79b15e9
CF
231 /* fall through intentionally */
232
233 case PROC_REATTACH_CHILD:
8cb359d9
CF
234 procs[nprocs] = vchild;
235 rc = procs[nprocs].wait ();
236 if (rc)
3ecfcf57 237 {
8cb359d9
CF
238 sigproc_printf ("added pid %d to proc table, slot %d", vchild->pid,
239 nprocs);
240 nprocs++;
3ecfcf57 241 }
9aa07a8f 242 break;
f02f1f14 243
164a681c
CF
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
c6cb7f8f 251 if (wval->pid == -1 || !wval->pid)
164a681c
CF
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 {
8cb359d9
CF
264 wval->ev = wval->thread_ev = CreateEvent (&sec_none_nih, TRUE, FALSE,
265 NULL);
f8a8e7a1 266 ProtectHandle1 (wval->ev, wq_ev);
164a681c
CF
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. */
56a19715 273 clearing = false;
164a681c
CF
274 goto scan_wait;
275
56a19715
CF
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
f02f1f14 283 /* Clear all waiting threads. Called from exceptions.cc prior to
0670609d
CF
284 the main thread's dispatch to a signal handler function.
285 (called from wait_sig thread) */
f02f1f14
CF
286 case PROC_CLEARWAIT:
287 /* Clear all "wait"ing threads. */
d3bda1df 288 if (val)
a5a965ff 289 sigproc_printf ("clear waiting threads");
d3bda1df 290 else
6a53b213 291 sigproc_printf ("looking for processes to reap, nprocs %d", nprocs);
9aa07a8f 292 clearing = val;
f02f1f14 293
1fd5e000
CF
294 scan_wait:
295 /* Scan the linked list of wait()ing threads. If a wait's parameters
e3778517 296 match this pid, then activate it. */
1fd5e000
CF
297 for (w = &waitq_head; w->next != NULL; w = w->next)
298 {
299 if ((potential_match = checkstate (w)) > 0)
a5a965ff 300 sigproc_printf ("released waiting thread");
164a681c 301 else if (!clearing && !(w->next->options & WNOHANG) && potential_match < 0)
a5a965ff 302 sigproc_printf ("only found non-terminated children");
f02f1f14 303 else if (potential_match <= 0) // nothing matched
1fd5e000 304 {
a5a965ff 305 sigproc_printf ("waiting thread found no children");
1fd5e000 306 HANDLE oldw = w->next->ev;
164a681c 307 w->next->pid = 0;
f02f1f14
CF
308 if (clearing)
309 w->next->status = -1; /* flag that a signal was received */
06571ff6 310 else if (!potential_match || !(w->next->options & WNOHANG))
71625490 311 w->next->ev = NULL;
1fd5e000
CF
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
f02f1f14 320 if (!clearing)
a5a965ff 321 sigproc_printf ("finished processing terminated/stopped child");
f02f1f14 322 else
1fd5e000 323 {
f02f1f14 324 waitq_head.next = NULL;
a5a965ff 325 sigproc_printf ("finished clearing");
1fd5e000 326 }
98f56d64
CF
327
328 if (global_sigs[SIGCHLD].sa_handler == (void *) SIG_IGN)
8cb359d9
CF
329 for (int i = 0; i < nprocs; i += remove_proc (i))
330 continue;
1fd5e000
CF
331 }
332
333out:
322c131f 334 sync_proc_subproc.release (); // Release the lock
1fd5e000 335out1:
a5a965ff 336 sigproc_printf ("returning %d", rc);
1fd5e000 337 return rc;
54dd79bb
CF
338#undef wval
339#undef vchild
1fd5e000
CF
340}
341
f8a8e7a1
CF
342// FIXME: This is inelegant
343void
168d7785 344_cygtls::remove_wq (DWORD wait)
f8a8e7a1 345{
5025bf33 346 if (exit_state < ES_FINAL && waitq_head.next && sync_proc_subproc
2c8fd406 347 && sync_proc_subproc.acquire (wait))
168d7785
CF
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 }
322c131f 356 sync_proc_subproc.release ();
168d7785 357 }
f8a8e7a1
CF
358}
359
08d944e1
CF
360inline void
361close_my_readsig ()
362{
363 HANDLE h;
364 if ((h = InterlockedExchangePointer (&my_readsig, NULL)))
365 ForceCloseHandle1 (h, my_readsig);
366}
367
4ab568c6
CF
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. */
371void
372_cygtls::signal_exit (int rc)
373{
e35f1d16 374 HANDLE myss = my_sendsig;
4ab568c6 375 my_sendsig = NULL; /* Make no_signals_allowed return true */
8f937028 376
e35f1d16
CF
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 }
c1dedea6 394 signal_debugger (rc & 0x7f);
4ab568c6
CF
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
4ab568c6 412 if ((rc & 0x80) && !try_to_debug ())
e52a43f1 413 stackdump (thread_context.ebp, true);
4ab568c6
CF
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
1fd5e000 427/* Terminate the wait_subproc thread.
f6f3b1ee
CF
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. */
1fd5e000 432void __stdcall
a611ae50 433proc_terminate ()
1fd5e000 434{
8cb359d9 435 sigproc_printf ("nprocs %d", nprocs);
8cb359d9 436 if (nprocs)
1fd5e000 437 {
322c131f 438 sync_proc_subproc.acquire (WPSP);
1fd5e000 439
0c55f6ed 440 proc_subproc (PROC_CLEARWAIT, 1);
1fd5e000 441
8cb359d9 442 /* Clean out proc processes from the pid list. */
56a19715 443 for (int i = 0; i < nprocs; i++)
1fd5e000 444 {
b79c0094
CF
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;
f181da27 449 if (procs[i].wait_thread)
56a19715 450 procs[i].wait_thread->terminate_thread ();
b79c0094
CF
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. */
cf22fb91
CF
456 if (procs[i] != myself)
457 procs[i].release ();
1fd5e000 458 }
8cb359d9 459 nprocs = 0;
322c131f 460 sync_proc_subproc.release ();
1fd5e000 461 }
a5a965ff 462 sigproc_printf ("leaving");
1fd5e000
CF
463}
464
7ac61736 465/* Clear pending signal */
1fd5e000 466void __stdcall
7ac61736 467sig_clear (int target_sig)
1fd5e000 468{
a611ae50 469 if (&_my_tls != _sig_tls)
7ac61736
CF
470 sig_send (myself, -target_sig);
471 else
472 {
f6936c48 473 sigpacket *q;
ca713cfa
CF
474 sigpacket *save = sigq.save ();
475 sigq.reset ();
476 while ((q = sigq.next ()))
f6936c48 477 if (q->si.si_signo == target_sig)
7ac61736 478 {
bcb4223c 479 q->si.si_signo = __SIGDELETE;
7ac61736
CF
480 break;
481 }
ca713cfa 482 sigq.restore (save);
7ac61736 483 }
1fd5e000
CF
484}
485
06bb4899 486extern "C" int
7ac61736 487sigpending (sigset_t *mask)
06bb4899 488{
7ac61736
CF
489 sigset_t outset = (sigset_t) sig_send (myself, __SIGPENDING);
490 if (outset == SIG_BAD_MASK)
491 return -1;
492 *mask = outset;
06bb4899
CF
493 return 0;
494}
495
7ac61736 496/* Force the wait_sig thread to wake up and scan for pending signals */
9e1ad59d
CF
497void __stdcall
498sig_dispatch_pending (bool fast)
1fd5e000 499{
ad37df48 500 if (exit_state || &_my_tls == _sig_tls)
29d52c8a
CF
501 {
502#ifdef DEBUGGING
a611ae50
CF
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);
29d52c8a 505#endif
9e1ad59d 506 return;
29d52c8a 507 }
a0d3c309 508
dc3dc498
CF
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);
1fd5e000
CF
516}
517
05726ddd 518/* Signal thread initialization. Called from dll_crt0_1.
b9874a0c 519 This routine starts the signal handling thread. */
1fd5e000
CF
520void __stdcall
521sigproc_init ()
522{
b9874a0c 523 char char_sa_buf[1024];
9f65451e
CF
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,
28c8ae66
CF
526 sizeof (sigpacket), "sigwait",
527 PIPE_ADD_PID);
9f65451e
CF
528 if (err)
529 {
530 SetLastError (err);
b9874a0c 531 api_fatal ("couldn't create signal pipe, %E");
9f65451e 532 }
b9874a0c
CF
533 ProtectHandle (my_readsig);
534 myself->sendsig = my_sendsig;
6a7d80f2 535 /* sync_proc_subproc is used by proc_subproc. It serializes
bbca1e4c 536 access to the children and proc arrays. */
322c131f 537 sync_proc_subproc.init ("sync_proc_subproc");
56a19715 538 new cygthread (wait_sig, cygself, "sig");
1fd5e000
CF
539}
540
541/* Called on process termination to terminate signal and process threads.
542 */
543void __stdcall
a611ae50 544sigproc_terminate (exit_states es)
1fd5e000 545{
a611ae50
CF
546 exit_states prior_exit_state = exit_state;
547 exit_state = es;
f8af64be
CF
548 if (!cygwin_finished_initializing)
549 sigproc_printf ("don't worry about signal thread");
550 else if (prior_exit_state >= ES_FINAL)
67483cb2 551 sigproc_printf ("already performed");
5ec14fe4
CF
552 else
553 {
554 sigproc_printf ("entering");
6f96c536 555 sig_send (myself_nowait, __SIGEXIT);
67483cb2 556 proc_terminate (); // clean up process stuff
1fd5e000 557 }
1fd5e000
CF
558}
559
f6936c48
CF
560int __stdcall
561sig_send (_pinfo *p, int sig)
562{
ad37df48
CF
563 if (sig == __SIGHOLD)
564 sigheld = true;
565 else if (!sigheld)
566 /* nothing */;
51f90b2f
CF
567 else if (sig == __SIGFLUSH || sig == __SIGFLUSHFAST)
568 return 0;
f02400f7 569 else if (sig == __SIGNOHOLD || sig == __SIGEXIT)
ad37df48
CF
570 {
571 SetEvent (sigCONT);
572 sigheld = false;
573 }
3b69aaa9 574 else if (&_my_tls == _main_tls)
bbca1e4c
CF
575 {
576#ifdef DEBUGGING
a9396868 577 system_printf ("signal %d sent to %p while signals are on hold", sig, p);
bbca1e4c
CF
578#endif
579 return -1;
580 }
985d0e68 581 siginfo_t si = {0};
f6936c48
CF
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
1fd5e000 588/* Send a signal to another process by raising its signal semaphore.
f6936c48
CF
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. */
1fd5e000 592int __stdcall
e431827c 593sig_send (_pinfo *p, siginfo_t& si, _cygtls *tls)
1fd5e000
CF
594{
595 int rc = 1;
2e008fb9 596 bool its_me;
7ac61736 597 HANDLE sendsig;
7759daa9 598 sigpacket pack;
0730fa07 599 bool communing = si.si_signo == __SIGCOMMUNE;
1fd5e000 600
39d06d71 601 pack.wakeup = NULL;
9a4d574b 602 bool wait_for_completion;
56a19715 603 if (!(its_me = (!have_execed && (p == NULL || p == myself || p == myself_nowait))))
67483cb2
CF
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 }
1fd5e000
CF
616 else
617 {
c529909f 618 if (no_signals_available (si.si_signo != __SIGEXIT))
d795119c 619 {
2380dfe1 620 set_errno (EAGAIN);
d795119c
CF
621 goto out; // Either exiting or not yet initializing
622 }
5e477e9a 623 wait_for_completion = p != myself_nowait && _my_tls.isinitialized () && !exit_state;
1fd5e000
CF
624 p = myself;
625 }
626
1fd5e000 627
1fd5e000 628 if (its_me)
67483cb2 629 sendsig = my_sendsig;
7ac61736 630 else
99a8fab5 631 {
54dd79bb
CF
632 HANDLE dupsig;
633 DWORD dwProcessId;
634 for (int i = 0; !p->sendsig && i < 10000; i++)
084ea510 635 yield ();
54dd79bb
CF
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 }
dcb091ca 652 HANDLE hp = OpenProcess (PROCESS_DUP_HANDLE, false, dwProcessId);
7ac61736 653 if (!hp)
deb648cc 654 {
7ac61736 655 __seterrno ();
2380dfe1 656 sigproc_printf ("OpenProcess failed, %E");
7ac61736
CF
657 goto out;
658 }
f7239090 659 VerifyHandle (hp);
b79b15e9
CF
660 if (!DuplicateHandle (hp, dupsig, GetCurrentProcess (), &sendsig, 0,
661 false, DUPLICATE_SAME_ACCESS) || !sendsig)
7ac61736
CF
662 {
663 __seterrno ();
54dd79bb
CF
664 sigproc_printf ("DuplicateHandle failed, %E");
665 CloseHandle (hp);
deb648cc
CF
666 goto out;
667 }
f7239090 668 VerifyHandle (sendsig);
0730fa07
CF
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;
f8b8b1be 677 if (!CreatePipeOverlapped (&fromthem, &tome, &sec_all_nih))
0730fa07
CF
678 {
679 sigproc_printf ("CreatePipe for __SIGCOMMUNE failed, %E");
680 __seterrno ();
681 goto out;
682 }
b79b15e9 683 if (!DuplicateHandle (GetCurrentProcess (), tome, hp, &tome, 0, false,
0730fa07
CF
684 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
685 {
686 sigproc_printf ("DuplicateHandle for __SIGCOMMUNE failed, %E");
687 __seterrno ();
688 goto out;
689 }
690 }
99a8fab5 691 }
1fd5e000 692
d795119c
CF
693 sigproc_printf ("sendsig %p, pid %d, signal %d, its_me %d", sendsig, p->pid, si.si_signo, its_me);
694
7759daa9
CF
695 sigset_t pending;
696 if (!its_me)
697 pack.mask = NULL;
f6936c48 698 else if (si.si_signo == __SIGPENDING)
7759daa9 699 pack.mask = &pending;
f6936c48 700 else if (si.si_signo == __SIGFLUSH || si.si_signo > 0)
9feffba7 701 pack.mask = tls ? &tls->sigmask : &_main_tls->sigmask;
7759daa9
CF
702 else
703 pack.mask = NULL;
704
f6936c48
CF
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;
7759daa9 710 pack.pid = myself->pid;
9feffba7 711 pack.tls = tls;
5e477e9a 712 if (wait_for_completion)
39d06d71
CF
713 {
714 pack.wakeup = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
715 sigproc_printf ("wakeup %p", pack.wakeup);
716 ProtectHandle (pack.wakeup);
717 }
718
0730fa07
CF
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);
4aedb287
CF
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;
0730fa07
CF
733 packsize = p - leader;
734 }
735
7ac61736 736 DWORD nb;
0730fa07 737 if (!WriteFile (sendsig, leader, packsize, &nb, NULL) || nb != packsize)
1fd5e000 738 {
7759daa9 739 /* Couldn't send to the pipe. This probably means that the
e3778517 740 process is exiting. */
1fd5e000 741 if (!its_me)
7ac61736 742 {
2380dfe1 743 sigproc_printf ("WriteFile for pipe %p failed, %E", sendsig);
7ac61736
CF
744 ForceCloseHandle (sendsig);
745 }
1fd5e000
CF
746 else
747 {
c529909f 748 if (no_signals_available (true))
a5a965ff 749 sigproc_printf ("I'm going away now");
fdd857a1 750 else if (!p->exec_sendsig)
7ac61736 751 system_printf ("error sending signal %d to pid %d, pipe handle %p, %E",
fdd857a1 752 si.si_signo, p->pid, sendsig);
1fd5e000 753 }
4ab568c6
CF
754 if (GetLastError () == ERROR_BROKEN_PIPE)
755 set_errno (ESRCH);
756 else
757 __seterrno ();
1fd5e000
CF
758 goto out;
759 }
760
7ac61736 761
7759daa9
CF
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)
7ac61736 769 {
7759daa9
CF
770 sigproc_printf ("Waiting for pack.wakeup %p", pack.wakeup);
771 rc = WaitForSingleObject (pack.wakeup, WSSC);
255e7e55 772 ForceCloseHandle (pack.wakeup);
7ac61736 773 }
7759daa9 774 else
1fd5e000 775 {
68997e88 776 rc = WAIT_OBJECT_0;
f6936c48
CF
777 sigproc_printf ("Not waiting for sigcomplete. its_me %d signal %d",
778 its_me, si.si_signo);
68997e88 779 if (!its_me)
7ac61736 780 ForceCloseHandle (sendsig);
1fd5e000 781 }
1fd5e000 782
255e7e55 783 pack.wakeup = NULL;
1fd5e000
CF
784 if (rc == WAIT_OBJECT_0)
785 rc = 0; // Successful exit
786 else
787 {
882dfbf7 788 if (!no_signals_available (true))
f6111483 789 system_printf ("wait for sig_complete event failed, signal %d, rc %d, %E",
f6936c48 790 si.si_signo, rc);
1fd5e000
CF
791 set_errno (ENOSYS);
792 rc = -1;
793 }
794
9e1ad59d 795 if (wait_for_completion && si.si_signo != __SIGFLUSHFAST)
e431827c 796 _my_tls.call_signal_handler ();
0730fa07 797 goto out;
0670609d 798
1fd5e000 799out:
0730fa07
CF
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 }
39d06d71
CF
807 if (pack.wakeup)
808 ForceCloseHandle (pack.wakeup);
f6936c48 809 if (si.si_signo != __SIGPENDING)
7ac61736
CF
810 /* nothing */;
811 else if (!rc)
812 rc = (int) pending;
813 else
814 rc = SIG_BAD_MASK;
f6936c48 815 sigproc_printf ("returning %p from sending signal %d", rc, si.si_signo);
1fd5e000
CF
816 return rc;
817}
818
c9241c26 819int child_info::retry_count = 0;
56a19715 820
1fd5e000
CF
821/* Initialize some of the memory block passed to child processes
822 by fork/spawn/exec. */
56a19715 823child_info::child_info (unsigned in_cb, child_info_types chtype,
5f38ec46
CF
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),
1fb6667f
CF
827 flag (0), retry (child_info::retry_count), rd_proc_pipe (NULL),
828 wr_proc_pipe (NULL)
1fd5e000 829{
7dfad3a0
CF
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
62d172bb
CV
846 Note: It turns out that a non-zero value *does* harm operation on
847 XP 64 and 2K3 64 (Crash in CreateProcess call).
7dfad3a0
CF
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. */
62d172bb 853 msv_count = wincap.needs_count_in_si_lpres2 () ? in_cb / 5 : 0;
c16548b2 854
54dd79bb
CF
855 fhandler_union_cb = sizeof (fhandler_union);
856 user_h = cygwin_user_h;
ef8bff85 857 if (strace.active ())
76ef40d6 858 flag |= _CI_STRACED;
e8454a34 859 if (need_subproc_ready)
76ef40d6
CF
860 {
861 subproc_ready = CreateEvent (&sec_all, FALSE, FALSE, NULL);
862 flag |= _CI_ISCYGWIN;
863 }
54dd79bb 864 sigproc_printf ("subproc_ready %p", subproc_ready);
ce95c640
CF
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;
f16706de 868 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
b79b15e9 869 GetCurrentProcess (), &parent, 0, true,
ce95c640
CF
870 DUPLICATE_SAME_ACCESS))
871 system_printf ("couldn't create handle to myself for child, %E");
54dd79bb
CF
872}
873
874child_info::~child_info ()
875{
1fb6667f 876 cleanup ();
54dd79bb
CF
877}
878
879child_info_fork::child_info_fork () :
1fb6667f
CF
880 child_info (sizeof *this, _CH_FORK, true),
881 forker_finished (NULL)
54dd79bb
CF
882{
883}
884
e8454a34
CF
885child_info_spawn::child_info_spawn (child_info_types chtype, bool need_subproc_ready) :
886 child_info (sizeof *this, chtype, need_subproc_ready)
54dd79bb 887{
56a19715
CF
888 if (type == _CH_EXEC)
889 {
890 hExeced = NULL;
1fb6667f 891 if (my_wr_proc_pipe)
56a19715
CF
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
7b2740dd
CF
902cygheap_exec_info *
903cygheap_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
6daf4afb
CF
910void
911child_info_spawn::wait_for_myself ()
912{
b7d95b5b 913 postfork (myself);
6daf4afb
CF
914 myself.remember (false);
915 WaitForSingleObject (ev, INFINITE);
916}
917
1fb6667f
CF
918void
919child_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
56a19715
CF
943void
944child_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;
56a19715
CF
959 if (ev)
960 {
961 CloseHandle (ev);
962 ev = NULL;
963 }
56a19715
CF
964 if (type == _CH_EXEC)
965 {
966 if (iscygwin () && hExeced)
56a19715 967 proc_subproc (PROC_EXEC_CLEANUP, 0);
56a19715
CF
968 sync_proc_subproc.release ();
969 }
970 type = _CH_NADA;
1fb6667f 971 child_info::cleanup ();
54dd79bb
CF
972}
973
b79b15e9
CF
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. */
7b2740dd
CF
977inline void
978cygheap_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
b79b15e9
CF
987void
988child_info_spawn::record_children ()
989{
56a19715 990 if (type == _CH_EXEC && iscygwin ())
7b2740dd 991 moreinfo->record_children ();
b79b15e9
CF
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? */
7b2740dd
CF
997inline void
998cygheap_exec_info::reattach_children (HANDLE parent)
b79b15e9
CF
999{
1000 for (int i = 0; i < nchildren; i++)
1001 {
56a19715 1002 pinfo p (parent, children[i].p, children[i].pid);
277753c8 1003 if (!p)
56a19715 1004 debug_only_printf ("couldn't reattach child %d from previous process", children[i].pid);
26601df4 1005 else if (!p.reattach ())
56a19715
CF
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);
b79b15e9
CF
1011 }
1012}
1013
7b2740dd
CF
1014void
1015child_info_spawn::reattach_children ()
1016{
1017 moreinfo->reattach_children (parent);
1018}
1019
54dd79bb
CF
1020void
1021child_info::ready (bool execed)
1022{
1023 if (!subproc_ready)
1024 {
1025 sigproc_printf ("subproc_ready not set");
1026 return;
1027 }
1028
d3b593aa
CF
1029 if (dynamically_loaded)
1030 sigproc_printf ("not really ready");
1031 else if (!SetEvent (subproc_ready))
56a19715 1032 api_fatal ("SetEvent failed, %E");
54dd79bb
CF
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
1043bool
267e201d 1044child_info::sync (pid_t pid, HANDLE& hProcess, DWORD howlong)
54dd79bb 1045{
267e201d 1046 bool res;
0cdcb234
CF
1047 HANDLE w4[2];
1048 unsigned n = 0;
1049 unsigned nsubproc_ready;
1050
1051 if (!subproc_ready)
1052 nsubproc_ready = WAIT_OBJECT_0 + 3;
267e201d 1053 else
54dd79bb 1054 {
0cdcb234
CF
1055 w4[n++] = subproc_ready;
1056 nsubproc_ready = 0;
1057 }
1058 w4[n++] = hProcess;
54dd79bb 1059
0cdcb234
CF
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 {
84d38174 1065 system_printf ("wait failed, pid %u, %E", pid);
0cdcb234
CF
1066 res = false;
1067 }
1068 else
1069 {
84d38174 1070 if (x != nsubproc_ready)
a9396868
CF
1071 {
1072 res = false;
1073 GetExitCodeProcess (hProcess, &exit_code);
1074 }
84d38174 1075 else
267e201d 1076 {
a9396868
CF
1077 res = true;
1078 exit_code = STILL_ACTIVE;
1fb6667f 1079 if (type == _CH_EXEC && my_wr_proc_pipe)
84d38174
CF
1080 {
1081 ForceCloseHandle1 (hProcess, childhProc);
1082 hProcess = NULL;
1083 }
267e201d 1084 }
f4bb53c4
CF
1085 sigproc_printf ("pid %u, WFMO returned %d, exit_code %p, res %d", pid, x,
1086 exit_code, res);
54dd79bb
CF
1087 }
1088 return res;
1fd5e000
CF
1089}
1090
a9396868
CF
1091DWORD
1092child_info::proc_retry (HANDLE h)
1093{
3b69aaa9
CF
1094 if (!exit_code)
1095 return EXITCODE_OK;
f4bb53c4 1096 sigproc_printf ("exit_code %p", exit_code);
a9396868
CF
1097 switch (exit_code)
1098 {
1099 case STILL_ACTIVE: /* shouldn't happen */
1100 sigproc_printf ("STILL_ACTIVE? How'd we get here?");
1101 break;
93d606f6 1102 case STATUS_DLL_NOT_FOUND:
f4bb53c4 1103 case STATUS_ACCESS_VIOLATION:
f6ba9446 1104 case STATUS_ILLEGAL_INSTRUCTION:
dc4e4aab
CW
1105 case STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION: /* pseudo-reloc.c specific */
1106 return exit_code;
a9396868 1107 case STATUS_CONTROL_C_EXIT:
6813f009
CF
1108 if (saw_ctrl_c ())
1109 return EXITCODE_OK;
1110 /* fall through intentionally */
a9396868
CF
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;
85510878
CF
1117 case EXITCODE_FORK_FAILED: /* windows prevented us from forking */
1118 break;
b86f999a 1119
a9396868
CF
1120 /* Count down non-recognized exit codes more quickly since they aren't
1121 due to known conditions. */
1122 default:
eb285e11 1123 if (!iscygwin () && (exit_code & 0xffff0000) != 0xc0000000)
a9396868
CF
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
1135bool
44d2fc0a 1136child_info_fork::abort (const char *fmt, ...)
a9396868 1137{
44d2fc0a
CF
1138 if (fmt)
1139 {
1140 va_list ap;
1141 va_start (ap, fmt);
29649132 1142 strace_vprintf (SYSTEM, fmt, ap);
bb2b641c 1143 TerminateProcess (GetCurrentProcess (), EXITCODE_FORK_FAILED);
44d2fc0a 1144 }
a9396868 1145 if (retry > 0)
bb2b641c 1146 TerminateProcess (GetCurrentProcess (), EXITCODE_RETRY);
44d2fc0a 1147 return false;
a9396868
CF
1148}
1149
1fd5e000
CF
1150/* Check the state of all of our children to see if any are stopped or
1151 * terminated.
1152 */
1153static int __stdcall
164a681c 1154checkstate (waitq *parent_w)
1fd5e000 1155{
164a681c 1156 int potential_match = 0;
1fd5e000 1157
8cb359d9 1158 sigproc_printf ("nprocs %d", nprocs);
1fd5e000
CF
1159
1160 /* Check already dead processes first to see if they match the criteria
8cb359d9
CF
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])))
1fd5e000 1165 {
8cb359d9 1166 remove_proc (i);
1fd5e000
CF
1167 potential_match = 1;
1168 goto out;
1169 }
1170
8cb359d9
CF
1171 sigproc_printf ("no matching terminated children found");
1172 potential_match = -!!nprocs;
1fd5e000
CF
1173
1174out:
a5a965ff 1175 sigproc_printf ("returning %d", potential_match);
1fd5e000
CF
1176 return potential_match;
1177}
1178
8cb359d9
CF
1179/* Remove a proc from procs by swapping it with the last child in the list.
1180 Also releases shared memory of exited processes. */
1181static bool __stdcall
1182remove_proc (int ci)
1fd5e000 1183{
56a19715 1184 if (have_execed)
480b13a3
CF
1185 {
1186 if (_my_tls._ctinfo != procs[ci].wait_thread)
1187 procs[ci].wait_thread->terminate_thread ();
1188 }
56a19715 1189 else if (procs[ci]->exists ())
8cb359d9 1190 return true;
84c7d409 1191
8cb359d9
CF
1192 sigproc_printf ("removing procs[%d], pid %d, nprocs %d", ci, procs[ci]->pid,
1193 nprocs);
1194 if (procs[ci] != myself)
56a19715 1195 procs[ci].release ();
8cb359d9 1196 if (ci < --nprocs)
37d5841f
CF
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. */
cc07096c 1202 if (!have_execed && !exit_state)
15660c23
CF
1203 while (!procs[nprocs].waiter_ready)
1204 yield ();
37d5841f
CF
1205 procs[ci] = procs[nprocs];
1206 }
8cb359d9 1207 return 0;
1fd5e000
CF
1208}
1209
1210/* Check status of child process vs. waitq member.
264f41f0 1211
8cb359d9
CF
1212 parent_w is the pointer to the parent of the waitq member in question.
1213 child is the subprocess being considered.
264f41f0 1214
8cb359d9
CF
1215 Returns non-zero if waiting thread released. */
1216static bool __stdcall
84c7d409 1217stopped_or_terminated (waitq *parent_w, _pinfo *child)
1fd5e000 1218{
8cb359d9 1219 int might_match;
1fd5e000
CF
1220 waitq *w = parent_w->next;
1221
962f9a2c 1222 sigproc_printf ("considering pid %d, pgid %d, w->pid %d", child->pid, child->pgid, w->pid);
1fd5e000 1223 if (w->pid == -1)
8cb359d9 1224 might_match = 1;
1fd5e000 1225 else if (w->pid == 0)
8cb359d9 1226 might_match = child->pgid == myself->pgid;
1fd5e000 1227 else if (w->pid < 0)
8cb359d9 1228 might_match = child->pgid == -w->pid;
1fd5e000 1229 else
8cb359d9 1230 might_match = (w->pid == child->pid);
1fd5e000 1231
8cb359d9 1232 if (!might_match)
6a712635 1233 return false;
1fd5e000 1234
8cb359d9 1235 int terminated;
1fd5e000 1236
b66dba56 1237 if (!((terminated = (child->process_state == PID_EXITED))
ff7b364c
CF
1238 || ((w->options & WCONTINUED) && child->stopsig == SIGCONT)
1239 || ((w->options & WUNTRACED) && child->stopsig && child->stopsig != SIGCONT)))
6a712635 1240 return false;
1fd5e000 1241
8cb359d9
CF
1242 parent_w->next = w->next; /* successful wait. remove from wait queue */
1243 w->pid = child->pid;
1fd5e000 1244
8cb359d9
CF
1245 if (!terminated)
1246 {
56a19715 1247 sigproc_printf ("stopped child, stop signal %d", child->stopsig);
acced2ce
CF
1248 if (child->stopsig == SIGCONT)
1249 w->status = __W_CONTINUED;
1250 else
1251 w->status = (child->stopsig << 8) | 0x7f;
8cb359d9
CF
1252 child->stopsig = 0;
1253 }
85b3fb96 1254 else
8cb359d9 1255 {
5069a2b0 1256 child->process_state = PID_REAPED;
85b3fb96 1257 w->status = (__uint16_t) child->exitcode;
1fd5e000 1258
8cb359d9
CF
1259 add_rusage (&myself->rusage_children, &child->rusage_children);
1260 add_rusage (&myself->rusage_children, &child->rusage_self);
1fd5e000 1261
8cb359d9
CF
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 }
1fd5e000
CF
1267 }
1268
8cb359d9
CF
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;
1fd5e000
CF
1272}
1273
831d6fa5 1274static void
81010d21 1275talktome (siginfo_t *si)
831d6fa5 1276{
267e201d
CF
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)
0730fa07
CF
1280 {
1281 size_t n;
1282 DWORD nb;
81010d21 1283 if (!ReadFile (my_readsig, &n, sizeof (n), &nb, NULL) || nb != sizeof (n))
0730fa07 1284 return;
267e201d
CF
1285 siginfo_t *newsi = (siginfo_t *) alloca (size += n + 1);
1286 *newsi = *si;
1287 newsi->_si_commune._si_str = (char *) (newsi + 1);
81010d21 1288 if (!ReadFile (my_readsig, newsi->_si_commune._si_str, n, &nb, NULL) || nb != n)
0730fa07 1289 return;
267e201d
CF
1290 newsi->_si_commune._si_str[n] = '\0';
1291 si = newsi;
0730fa07 1292 }
267e201d
CF
1293
1294 pinfo pi (si->si_pid);
0730fa07 1295 if (pi)
b9aa8149 1296 new cygthread (commune_process, size, si, "commune");
831d6fa5
CF
1297}
1298
7ac61736 1299void
f6936c48 1300pending_signals::add (sigpacket& pack)
7ac61736 1301{
f6936c48 1302 sigpacket *se;
474048c2
CF
1303 if (sigs[pack.si.si_signo].si.si_signo)
1304 return;
1305 se = sigs + pack.si.si_signo;
f6936c48 1306 *se = pack;
70300fdb 1307 se->mask = &pack.tls->sigmask;
7ac61736
CF
1308 se->next = NULL;
1309 if (end)
1310 end->next = se;
1311 end = se;
1312 if (!start.next)
1313 start.next = se;
7ac61736
CF
1314}
1315
1316void
1317pending_signals::del ()
1318{
f6936c48 1319 sigpacket *next = curr->next;
7ac61736 1320 prev->next = next;
f6936c48 1321 curr->si.si_signo = 0;
7ac61736
CF
1322#ifdef DEBUGGING
1323 curr->next = NULL;
1324#endif
1325 if (end == curr)
1326 end = prev;
7ac61736
CF
1327 curr = next;
1328}
1329
f6936c48 1330sigpacket *
7ac61736
CF
1331pending_signals::next ()
1332{
f6936c48 1333 sigpacket *res;
7ac61736
CF
1334 prev = curr;
1335 if (!curr || !(curr = curr->next))
9a4d574b 1336 res = NULL;
7ac61736 1337 else
9a4d574b
CF
1338 res = curr;
1339 return res;
7ac61736
CF
1340}
1341
1342/* Process signals by waiting for signal data to arrive in a pipe.
1343 Set a completion event if one was specified. */
b9874a0c 1344static void WINAPI
529649f9 1345wait_sig (VOID *)
1fd5e000 1346{
b9874a0c 1347 _sig_tls = &_my_tls;
e5aa298d 1348 sigCONT = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
1fd5e000 1349
12b33712
CF
1350 sigproc_printf ("entering ReadFile loop, my_readsig %p, my_sendsig %p",
1351 my_readsig, my_sendsig);
2d1d1eb1 1352
936e4018 1353 sigpacket pack;
43c23d4b 1354 pack.si.si_signo = 0;
0d675c5d 1355 for (;;)
1fd5e000 1356 {
51f90b2f
CF
1357 if (pack.si.si_signo == __SIGHOLD)
1358 WaitForSingleObject (sigCONT, INFINITE);
7ac61736 1359 DWORD nb;
936e4018 1360 pack.tls = NULL;
81010d21 1361 if (!ReadFile (my_readsig, &pack, sizeof (pack), &nb, NULL))
7ac61736 1362 break;
1fd5e000 1363
7759daa9 1364 if (nb != sizeof (pack))
018a91fa 1365 {
7759daa9
CF
1366 system_printf ("short read from signal pipe: %d != %d", nb,
1367 sizeof (pack));
7ac61736 1368 continue;
018a91fa 1369 }
1fd5e000 1370
f6936c48 1371 if (!pack.si.si_signo)
9a4d574b
CF
1372 {
1373#ifdef DEBUGGING
1374 system_printf ("zero signal?");
1375#endif
1376 continue;
1377 }
7ac61736 1378
7759daa9
CF
1379 sigset_t dummy_mask;
1380 if (!pack.mask)
1fd5e000 1381 {
70300fdb 1382 dummy_mask = _main_tls->sigmask;
7759daa9 1383 pack.mask = &dummy_mask;
1fd5e000
CF
1384 }
1385
f6936c48 1386 sigpacket *q;
a5eb75d6 1387 bool clearwait = false;
f6936c48 1388 switch (pack.si.si_signo)
90f4768b 1389 {
7ac61736 1390 case __SIGCOMMUNE:
81010d21 1391 talktome (&pack.si);
9a4d574b 1392 break;
7ac61736 1393 case __SIGSTRACE:
8942ed09 1394 strace.activate (false);
9a4d574b 1395 break;
7ac61736 1396 case __SIGPENDING:
7759daa9 1397 *pack.mask = 0;
7ac61736 1398 unsigned bit;
ca713cfa
CF
1399 sigq.reset ();
1400 while ((q = sigq.next ()))
70300fdb 1401 if (pack.tls->sigmask & (bit = SIGTOMASK (q->si.si_signo)))
7759daa9 1402 *pack.mask |= bit;
7ac61736 1403 break;
d584454c 1404 case __SIGHOLD:
ede284de 1405 goto loop;
d584454c
CF
1406 break;
1407 case __SIGNOHOLD:
a5eb75d6
CF
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 }
d584454c 1419 break;
a611ae50 1420 case __SIGEXIT:
b9874a0c 1421 my_sendsig = NULL;
a611ae50
CF
1422 sigproc_printf ("saw __SIGEXIT");
1423 break; /* handle below */
852908e8
CV
1424 case __SIGSETPGRP:
1425 init_console_handler (true);
1426 break;
7ac61736 1427 default:
f6936c48
CF
1428 if (pack.si.si_signo < 0)
1429 sig_clear (-pack.si.si_signo);
27ec638b 1430 else
90f4768b 1431 {
9e1ad59d 1432 int sig = pack.si.si_signo;
b9ebff64
CF
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)
56a19715 1437 sigproc_printf ("signal %d already queued", pack.si.si_signo);
85427a94 1438 else
29d52c8a 1439 {
85427a94
CF
1440 int sigres = pack.process ();
1441 if (sigres <= 0)
1442 {
76832a5b 1443#ifdef DEBUGGING2
85427a94 1444 if (!sigres)
fa0b926a 1445 system_printf ("Failed to arm signal %d from pid %d", pack.si.si_signo, pack.pid);
29d52c8a 1446#endif
85427a94
CF
1447 sigq.add (pack); // FIXME: Shouldn't add this in !sh condition
1448 }
29d52c8a 1449 }
9e1ad59d 1450 if (sig == SIGCHLD)
a5eb75d6 1451 clearwait = true;
90f4768b 1452 }
7ac61736 1453 break;
d688945c 1454 }
a5eb75d6
CF
1455 if (clearwait)
1456 proc_subproc (PROC_CLEARWAIT, 0);
ede284de 1457 loop:
7759daa9 1458 if (pack.wakeup)
39d06d71 1459 {
f02b22dc 1460 sigproc_printf ("signalling pack.wakeup %p", pack.wakeup);
39d06d71 1461 SetEvent (pack.wakeup);
39d06d71 1462 }
a611ae50
CF
1463 if (pack.si.si_signo == __SIGEXIT)
1464 break;
1fd5e000
CF
1465 }
1466
08d944e1 1467 close_my_readsig ();
5e477e9a
CF
1468 sigproc_printf ("signal thread exiting");
1469 ExitThread (0);
1fd5e000 1470}
This page took 0.712889 seconds and 5 git commands to generate.