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