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