1/* Copyright (C) 1991-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include <lock-intern.h> /* For `struct mutex'. */
23#include <pthreadP.h>
24#include <mach.h>
25#include <mach/thread_switch.h>
26#include <mach/mig_support.h>
27#include <mach/vm_param.h>
28
29#include <hurd.h>
30#include <hurd/id.h>
31#include <hurd/signal.h>
32
33#include "hurdfault.h"
34#include "hurdmalloc.h" /* XXX */
35#include "../locale/localeinfo.h"
36
37#include <libc-diag.h>
38
39const char *_hurdsig_getenv (const char *);
40
41struct mutex _hurd_siglock;
42int _hurd_stopped;
43
44/* Port that receives signals and other miscellaneous messages. */
45mach_port_t _hurd_msgport;
46
47/* Thread listening on it. */
48thread_t _hurd_msgport_thread;
49
50/* These are set up by _hurdsig_init. */
51unsigned long int __hurd_sigthread_stack_base;
52unsigned long int __hurd_sigthread_stack_end;
53
54/* Linked-list of per-thread signal state. */
55struct hurd_sigstate *_hurd_sigstates;
56
57/* Sigstate for the task-global signals. */
58struct hurd_sigstate *_hurd_global_sigstate;
59
60/* Timeout for RPC's after interrupt_operation. */
61mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 60000;
62
63static void
64default_sigaction (struct sigaction actions[NSIG])
65{
66 int signo;
67
68 __sigemptyset (set: &actions[0].sa_mask);
69 actions[0].sa_flags = SA_RESTART;
70 actions[0].sa_handler = SIG_DFL;
71
72 for (signo = 1; signo < NSIG; ++signo)
73 actions[signo] = actions[0];
74}
75
76struct hurd_sigstate *
77_hurd_thread_sigstate (thread_t thread)
78{
79 struct hurd_sigstate *ss;
80 __mutex_lock (&_hurd_siglock);
81 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
82 if (ss->thread == thread)
83 break;
84 if (ss == NULL)
85 {
86 ss = malloc (sizeof (*ss));
87 if (ss == NULL)
88 __libc_fatal (message: "hurd: Can't allocate sigstate\n");
89 __spin_lock_init (&ss->critical_section_lock);
90 __spin_lock_init (&ss->lock);
91 ss->thread = thread;
92
93 /* Initialize default state. */
94 __sigemptyset (set: &ss->blocked);
95 __sigemptyset (set: &ss->pending);
96 memset (s: &ss->sigaltstack, c: 0, n: sizeof (ss->sigaltstack));
97 ss->sigaltstack.ss_flags |= SS_DISABLE;
98 ss->preemptors = NULL;
99 ss->suspended = MACH_PORT_NULL;
100 ss->intr_port = MACH_PORT_NULL;
101 ss->context = NULL;
102 ss->active_resources = NULL;
103 ss->cancel = 0;
104 ss->cancel_hook = NULL;
105
106 if (thread == MACH_PORT_NULL)
107 {
108 /* Process-wide sigstate, use the system defaults. */
109 default_sigaction (actions: ss->actions);
110
111 /* The global sigstate is not added to the _hurd_sigstates list.
112 It is created with _hurd_thread_sigstate (MACH_PORT_NULL)
113 but should be accessed through _hurd_global_sigstate. */
114 }
115 else
116 {
117 error_t err;
118
119 /* Use the global actions as a default for new threads. */
120 struct hurd_sigstate *s = _hurd_global_sigstate;
121 if (s)
122 {
123 __spin_lock (&s->lock);
124 memcpy (dest: ss->actions, src: s->actions, n: sizeof (s->actions));
125 __spin_unlock (&s->lock);
126 }
127 else
128 default_sigaction (actions: ss->actions);
129
130 ss->next = _hurd_sigstates;
131 _hurd_sigstates = ss;
132
133 err = __mach_port_mod_refs (__mach_task_self (), thread,
134 MACH_PORT_RIGHT_SEND, 1);
135 if (err)
136 __libc_fatal (message: "hurd: Can't add reference on Mach thread\n");
137 }
138 }
139 __mutex_unlock (&_hurd_siglock);
140 return ss;
141}
142libc_hidden_def (_hurd_thread_sigstate)
143
144/* Destroy a sigstate structure. Called by libpthread just before the
145 * corresponding thread is terminated. */
146void
147_hurd_sigstate_delete (thread_t thread)
148{
149 struct hurd_sigstate **ssp, *ss;
150
151 __mutex_lock (&_hurd_siglock);
152 for (ssp = &_hurd_sigstates; *ssp; ssp = &(*ssp)->next)
153 if ((*ssp)->thread == thread)
154 break;
155
156 ss = *ssp;
157 if (ss)
158 *ssp = ss->next;
159
160 __mutex_unlock (&_hurd_siglock);
161 if (ss)
162 {
163 if (ss->thread != MACH_PORT_NULL)
164 __mach_port_deallocate (__mach_task_self (), ss->thread);
165
166 free (ss);
167 }
168}
169
170/* Make SS a global receiver, with pthread signal semantics. */
171void
172_hurd_sigstate_set_global_rcv (struct hurd_sigstate *ss)
173{
174 assert (ss->thread != MACH_PORT_NULL);
175 ss->actions[0].sa_handler = SIG_IGN;
176}
177
178/* Check whether SS is a global receiver. */
179static int
180sigstate_is_global_rcv (const struct hurd_sigstate *ss)
181{
182 return (_hurd_global_sigstate != NULL)
183 && (ss->actions[0].sa_handler == SIG_IGN);
184}
185libc_hidden_def (_hurd_sigstate_delete)
186
187/* Lock/unlock a hurd_sigstate structure. If the accessors below require
188 it, the global sigstate will be locked as well. */
189void
190_hurd_sigstate_lock (struct hurd_sigstate *ss)
191{
192 if (sigstate_is_global_rcv (ss))
193 __spin_lock (&_hurd_global_sigstate->lock);
194 __spin_lock (&ss->lock);
195}
196void
197_hurd_sigstate_unlock (struct hurd_sigstate *ss)
198{
199 __spin_unlock (&ss->lock);
200 if (sigstate_is_global_rcv (ss))
201 __spin_unlock (&_hurd_global_sigstate->lock);
202}
203libc_hidden_def (_hurd_sigstate_set_global_rcv)
204
205/* Retreive a thread's full set of pending signals, including the global
206 ones if appropriate. SS must be locked. */
207sigset_t
208_hurd_sigstate_pending (const struct hurd_sigstate *ss)
209{
210 sigset_t pending = ss->pending;
211 if (sigstate_is_global_rcv (ss))
212 __sigorset (dest: &pending, left: &pending, right: &_hurd_global_sigstate->pending);
213 return pending;
214}
215
216/* Clear a pending signal and return the associated detailed
217 signal information. SS must be locked, and must have signal SIGNO
218 pending, either directly or through the global sigstate. */
219static struct hurd_signal_detail
220sigstate_clear_pending (struct hurd_sigstate *ss, int signo)
221{
222 if (sigstate_is_global_rcv (ss)
223 && __sigismember (set: &_hurd_global_sigstate->pending, sig: signo))
224 {
225 __sigdelset (set: &_hurd_global_sigstate->pending, sig: signo);
226 return _hurd_global_sigstate->pending_data[signo];
227 }
228
229 assert (__sigismember (set: &ss->pending, sig: signo));
230 __sigdelset (set: &ss->pending, sig: signo);
231 return ss->pending_data[signo];
232}
233libc_hidden_def (_hurd_sigstate_lock)
234libc_hidden_def (_hurd_sigstate_unlock)
235
236/* Retreive a thread's action vector. SS must be locked. */
237struct sigaction *
238_hurd_sigstate_actions (struct hurd_sigstate *ss)
239{
240 if (sigstate_is_global_rcv (ss))
241 return _hurd_global_sigstate->actions;
242 else
243 return ss->actions;
244}
245libc_hidden_def (_hurd_sigstate_pending)
246
247
248/* Signal delivery itself is on this page. */
249
250#include <hurd/fd.h>
251#include <hurd/crash.h>
252#include <hurd/resource.h>
253#include <hurd/paths.h>
254#include <setjmp.h>
255#include <fcntl.h>
256#include <sys/wait.h>
257#include <thread_state.h>
258#include <hurd/msg_server.h>
259#include <hurd/msg_reply.h> /* For __msg_sig_post_reply. */
260#include <hurd/interrupt.h>
261#include <assert.h>
262#include <unistd.h>
263
264
265/* Call the crash dump server to mummify us before we die.
266 Returns nonzero if a core file was written. */
267static int
268write_corefile (int signo, const struct hurd_signal_detail *detail)
269{
270 error_t err;
271 mach_port_t coreserver;
272 file_t file, coredir;
273 const char *name;
274
275 /* Don't bother locking since we just read the one word. */
276 rlim_t corelimit = _hurd_rlimits[RLIMIT_CORE].rlim_cur;
277
278 if (corelimit == 0)
279 /* No core dumping, thank you very much. Note that this makes
280 `ulimit -c 0' prevent crash-suspension too, which is probably
281 what the user wanted. */
282 return 0;
283
284 /* XXX RLIMIT_CORE:
285 When we have a protocol to make the server return an error
286 for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE
287 value in place of the RLIMIT_FSIZE value. */
288
289 /* First get a port to the core dumping server. */
290 coreserver = MACH_PORT_NULL;
291 name = _hurdsig_getenv ("CRASHSERVER");
292 if (name != NULL)
293 coreserver = __file_name_lookup (name, 0, 0);
294 if (coreserver == MACH_PORT_NULL)
295 coreserver = __file_name_lookup (_SERVERS_CRASH, 0, 0);
296 if (coreserver == MACH_PORT_NULL)
297 return 0;
298
299 /* Get a port to the directory where the new core file will reside. */
300 file = MACH_PORT_NULL;
301 name = _hurdsig_getenv ("COREFILE");
302 if (name == NULL)
303 name = "core";
304 coredir = __file_name_split (name, (char **) &name);
305 if (coredir != MACH_PORT_NULL)
306 /* Create the new file, but don't link it into the directory yet. */
307 __dir_mkfile (coredir, O_WRONLY|O_CREAT,
308 0600 & ~_hurd_umask, /* XXX ? */
309 &file);
310
311 /* Call the core dumping server to write the core file. */
312 err = __crash_dump_task (coreserver,
313 __mach_task_self (),
314 file,
315 signo, detail->code, detail->error,
316 detail->exc, detail->exc_code, detail->exc_subcode,
317 _hurd_ports[INIT_PORT_CTTYID].port,
318 MACH_MSG_TYPE_COPY_SEND);
319 __mach_port_deallocate (__mach_task_self (), coreserver);
320
321 if (! err && file != MACH_PORT_NULL)
322 /* The core dump into FILE succeeded, so now link it into the
323 directory. */
324 err = __dir_link (coredir, file, name, 1);
325 __mach_port_deallocate (__mach_task_self (), file);
326 __mach_port_deallocate (__mach_task_self (), coredir);
327 return !err && file != MACH_PORT_NULL;
328}
329
330
331/* The lowest-numbered thread state flavor value is 1,
332 so we use bit 0 in machine_thread_all_state.set to
333 record whether we have done thread_abort. */
334#define THREAD_ABORTED 1
335
336/* SS->thread is suspended. Abort the thread and get its basic state. */
337static void
338abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
339 void (*reply) (void))
340{
341 assert (ss->thread != MACH_PORT_NULL);
342
343 if (!(state->set & THREAD_ABORTED))
344 {
345 error_t err = __thread_abort (ss->thread);
346 assert_perror (err);
347 /* Clear all thread state flavor set bits, because thread_abort may
348 have changed the state. */
349 state->set = THREAD_ABORTED;
350 }
351
352 if (reply)
353 (*reply) ();
354
355 machine_get_basic_state (ss->thread, state);
356}
357
358/* Find the location of the MiG reply port cell in use by the thread whose
359 state is described by THREAD_STATE. If SIGTHREAD is nonzero, make sure
360 that this location can be set without faulting, or else return NULL. */
361
362static mach_port_t *
363interrupted_reply_port_location (thread_t thread,
364 struct machine_thread_all_state *thread_state,
365 int sigthread)
366{
367 mach_port_t *portloc = &THREAD_TCB(thread, thread_state)->reply_port;
368
369 if (sigthread && _hurdsig_catch_memory_fault (portloc))
370 /* Faulted trying to read the TCB. */
371 return NULL;
372
373 DIAG_PUSH_NEEDS_COMMENT;
374 /* GCC 6 and before seem to be confused by the setjmp call inside
375 _hurdsig_catch_memory_fault and think that we may be returning a second
376 time to here with portloc uninitialized (but we never do). */
377 DIAG_IGNORE_NEEDS_COMMENT (6, "-Wmaybe-uninitialized");
378 /* Fault now if this pointer is bogus. */
379 *(volatile mach_port_t *) portloc = *portloc;
380 DIAG_POP_NEEDS_COMMENT;
381
382 if (sigthread)
383 _hurdsig_end_catch_fault ();
384
385 return portloc;
386}
387
388#include <hurd/sigpreempt.h>
389#include <intr-msg.h>
390
391/* Timeout on interrupt_operation calls. */
392mach_msg_timeout_t _hurdsig_interrupt_timeout = 1000;
393
394/* SS->thread is suspended.
395
396 Abort any interruptible RPC operation the thread is doing.
397
398 This uses only the constant member SS->thread and the unlocked, atomically
399 set member SS->intr_port, so no locking is needed.
400
401 If successfully sent an interrupt_operation and therefore the thread should
402 wait for its pending RPC to return (possibly EINTR) before taking the
403 incoming signal, returns the reply port to be received on. Otherwise
404 returns MACH_PORT_NULL.
405
406 SIGNO is used to find the applicable SA_RESTART bit. If SIGNO is zero,
407 the RPC fails with EINTR instead of restarting (thread_cancel).
408
409 *STATE_CHANGE is set nonzero if STATE->basic was modified and should
410 be applied back to the thread if it might ever run again, else zero. */
411
412mach_port_t
413_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
414 struct machine_thread_all_state *state, int *state_change,
415 void (*reply) (void))
416{
417 extern const void _hurd_intr_rpc_msg_about_to;
418 extern const void _hurd_intr_rpc_msg_in_trap;
419 mach_port_t rcv_port = MACH_PORT_NULL;
420 mach_port_t intr_port;
421
422 *state_change = 0;
423
424 intr_port = ss->intr_port;
425 if (intr_port == MACH_PORT_NULL)
426 /* No interruption needs done. */
427 return MACH_PORT_NULL;
428
429 /* Abort the thread's kernel context, so any pending message send or
430 receive completes immediately or aborts. */
431 abort_thread (ss, state, reply);
432
433 if (state->basic.PC >= (natural_t) &_hurd_intr_rpc_msg_about_to
434 && state->basic.PC < (natural_t) &_hurd_intr_rpc_msg_in_trap)
435 {
436 /* The thread is about to do the RPC, but hasn't yet entered
437 mach_msg. Mutate the thread's state so it knows not to try
438 the RPC. */
439 INTR_MSG_BACK_OUT (&state->basic);
440 MACHINE_THREAD_STATE_SET_PC (&state->basic,
441 &_hurd_intr_rpc_msg_in_trap);
442 state->basic.SYSRETURN = MACH_SEND_INTERRUPTED;
443 *state_change = 1;
444 }
445 else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap
446 /* The thread was blocked in the system call. After thread_abort,
447 the return value register indicates what state the RPC was in
448 when interrupted. */
449 && state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
450 {
451 /* The RPC request message was sent and the thread was waiting for
452 the reply message; now the message receive has been aborted, so
453 the mach_msg call will return MACH_RCV_INTERRUPTED. We must tell
454 the server to interrupt the pending operation. The thread must
455 wait for the reply message before running the signal handler (to
456 guarantee that the operation has finished being interrupted), so
457 our nonzero return tells the trampoline code to finish the message
458 receive operation before running the handler. */
459
460 mach_port_t *reply = interrupted_reply_port_location (ss->thread,
461 state,
462 sigthread);
463 error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);
464
465 if (err)
466 {
467 if (reply)
468 {
469 /* The interrupt didn't work.
470 Destroy the receive right the thread is blocked on. */
471 __mach_port_destroy (__mach_task_self (), *reply);
472 *reply = MACH_PORT_NULL;
473 }
474
475 /* The system call return value register now contains
476 MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
477 call. Since we have just destroyed the receive right, the
478 retry will fail with MACH_RCV_INVALID_NAME. Instead, just
479 change the return value here to EINTR so mach_msg will not
480 retry and the EINTR error code will propagate up. */
481 state->basic.SYSRETURN = EINTR;
482 *state_change = 1;
483 }
484 else if (reply)
485 rcv_port = *reply;
486
487 /* All threads whose RPCs were interrupted by the interrupt_operation
488 call above will retry their RPCs unless we clear SS->intr_port.
489 So we clear it for the thread taking a signal when SA_RESTART is
490 clear, so that its call returns EINTR. */
491 if (! signo || !(_hurd_sigstate_actions (ss) [signo].sa_flags & SA_RESTART))
492 ss->intr_port = MACH_PORT_NULL;
493 }
494
495 return rcv_port;
496}
497
498
499/* Abort the RPCs being run by all threads but this one;
500 all other threads should be suspended. If LIVE is nonzero, those
501 threads may run again, so they should be adjusted as necessary to be
502 happy when resumed. STATE is clobbered as a scratch area; its initial
503 contents are ignored, and its contents on return are not useful. */
504
505static void
506abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
507{
508 /* We can just loop over the sigstates. Any thread doing something
509 interruptible must have one. We needn't bother locking because all
510 other threads are stopped. */
511
512 struct hurd_sigstate *ss;
513 size_t nthreads;
514 mach_port_t *reply_ports;
515
516 /* First loop over the sigstates to count them.
517 We need to know how big a vector we will need for REPLY_PORTS. */
518 nthreads = 0;
519 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
520 ++nthreads;
521
522 reply_ports = alloca (nthreads * sizeof *reply_ports);
523
524 nthreads = 0;
525 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, ++nthreads)
526 if (ss->thread == _hurd_msgport_thread)
527 reply_ports[nthreads] = MACH_PORT_NULL;
528 else
529 {
530 int state_changed;
531 state->set = 0; /* Reset scratch area. */
532
533 /* Abort any operation in progress with interrupt_operation.
534 Record the reply port the thread is waiting on.
535 We will wait for all the replies below. */
536 reply_ports[nthreads] = _hurdsig_abort_rpcs (ss, signo, 1,
537 state, &state_changed,
538 NULL);
539 if (live)
540 {
541 if (reply_ports[nthreads] != MACH_PORT_NULL)
542 {
543 /* We will wait for the reply to this RPC below, so the
544 thread must issue a new RPC rather than waiting for the
545 reply to the one it sent. */
546 state->basic.SYSRETURN = EINTR;
547 state_changed = 1;
548 }
549 if (state_changed)
550 /* Aborting the RPC needed to change this thread's state,
551 and it might ever run again. So write back its state. */
552 __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
553 (natural_t *) &state->basic,
554 MACHINE_THREAD_STATE_COUNT);
555 }
556 }
557
558 /* Wait for replies from all the successfully interrupted RPCs. */
559 while (nthreads-- > 0)
560 if (reply_ports[nthreads] != MACH_PORT_NULL)
561 {
562 error_t err;
563 mach_msg_header_t head;
564 err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
565 reply_ports[nthreads],
566 _hurd_interrupted_rpc_timeout, MACH_PORT_NULL);
567 switch (err)
568 {
569 case MACH_RCV_TIMED_OUT:
570 case MACH_RCV_TOO_LARGE:
571 break;
572
573 default:
574 assert_perror (err);
575 }
576 }
577}
578
579/* Wake up any sigsuspend or pselect call that is blocking SS->thread. SS must
580 be locked. */
581static void
582wake_sigsuspend (struct hurd_sigstate *ss)
583{
584 error_t err;
585 mach_msg_header_t msg;
586
587 if (ss->suspended == MACH_PORT_NULL)
588 return;
589
590 /* There is a sigsuspend waiting. Tell it to wake up. */
591 msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
592 msg.msgh_remote_port = ss->suspended;
593 msg.msgh_local_port = MACH_PORT_NULL;
594 /* These values do not matter. */
595 msg.msgh_id = 8675309; /* Jenny, Jenny. */
596 ss->suspended = MACH_PORT_NULL;
597 err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
598 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
599 MACH_PORT_NULL);
600 assert_perror (err);
601}
602
603struct hurd_signal_preemptor *_hurdsig_preemptors = 0;
604sigset_t _hurdsig_preempted_set;
605
606/* XXX temporary to deal with spelling fix */
607weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
608
609/* Mask of stop signals. */
610#define STOPSIGS (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) \
611 | __sigmask (SIGSTOP) | __sigmask (SIGTSTP))
612
613/* Actual delivery of a single signal. Called with SS unlocked. When
614 the signal is delivered, return SS, locked (or, if SS was originally
615 _hurd_global_sigstate, the sigstate of the actual thread the signal
616 was delivered to). If the signal is being traced, return NULL with
617 SS unlocked. */
618static struct hurd_sigstate *
619post_signal (struct hurd_sigstate *ss,
620 int signo, struct hurd_signal_detail *detail,
621 int untraced, void (*reply) (void))
622{
623 struct machine_thread_all_state thread_state;
624 enum { stop, ignore, core, term, handle } act;
625 int ss_suspended;
626
627 /* sigaction for preemptors */
628 struct sigaction preempt_sigaction = {
629 .sa_flags = SA_RESTART
630 };
631
632 struct sigaction *action;
633
634 /* Mark the signal as pending. */
635 void mark_pending (void)
636 {
637 __sigaddset (&ss->pending, signo);
638 /* Save the details to be given to the handler when SIGNO is
639 unblocked. */
640 ss->pending_data[signo] = *detail;
641 }
642
643 /* Suspend the process with SIGNO. */
644 void suspend (void)
645 {
646 /* Stop all other threads and mark ourselves stopped. */
647 __USEPORT (PROC,
648 ({
649 /* Hold the siglock while stopping other threads to be
650 sure it is not held by another thread afterwards. */
651 __mutex_lock (&_hurd_siglock);
652 __proc_dostop (port, _hurd_msgport_thread);
653 __mutex_unlock (&_hurd_siglock);
654 abort_all_rpcs (signo, &thread_state, 1);
655 reply ();
656 __proc_mark_stop (port, signo, detail->code);
657 }));
658 _hurd_stopped = 1;
659 }
660 /* Resume the process after a suspension. */
661 void resume (void)
662 {
663 /* Resume the process from being stopped. */
664 thread_t *threads;
665 mach_msg_type_number_t nthreads, i;
666 error_t err;
667
668 if (! _hurd_stopped)
669 return;
670
671 /* Tell the proc server we are continuing. */
672 __USEPORT (PROC, __proc_mark_cont (port));
673 /* Fetch ports to all our threads and resume them. */
674 err = __task_threads (__mach_task_self (), &threads, &nthreads);
675 assert_perror (err);
676 for (i = 0; i < nthreads; ++i)
677 {
678 if (act == handle && threads[i] == ss->thread)
679 {
680 /* The thread that will run the handler is kept suspended. */
681 ss_suspended = 1;
682 }
683 else if (threads[i] != _hurd_msgport_thread)
684 {
685 err = __thread_resume (threads[i]);
686 assert_perror (err);
687 }
688 err = __mach_port_deallocate (__mach_task_self (),
689 threads[i]);
690 assert_perror (err);
691 }
692 __vm_deallocate (__mach_task_self (),
693 (vm_address_t) threads,
694 nthreads * sizeof *threads);
695 _hurd_stopped = 0;
696 }
697
698 error_t err;
699 sighandler_t handler;
700
701 if (signo == 0)
702 {
703 if (untraced)
704 {
705 /* This is PTRACE_CONTINUE. */
706 act = ignore;
707 resume ();
708 }
709
710 /* This call is just to check for pending signals. */
711 _hurd_sigstate_lock (ss);
712 return ss;
713 }
714
715 thread_state.set = 0; /* We know nothing. */
716
717 _hurd_sigstate_lock (ss);
718
719 /* If this is a global signal, try to find a thread ready to accept
720 it right away. This is especially important for untraced signals,
721 since going through the global pending mask would de-untrace them. */
722 if (ss->thread == MACH_PORT_NULL)
723 {
724 struct hurd_sigstate *rss;
725
726 __mutex_lock (&_hurd_siglock);
727 for (rss = _hurd_sigstates; rss != NULL; rss = rss->next)
728 {
729 if (! sigstate_is_global_rcv (ss: rss))
730 continue;
731
732 /* The global sigstate is already locked. */
733 __spin_lock (&rss->lock);
734 if (! __sigismember (set: &rss->blocked, sig: signo))
735 {
736 ss = rss;
737 break;
738 }
739 __spin_unlock (&rss->lock);
740 }
741 __mutex_unlock (&_hurd_siglock);
742 }
743
744 /* We want the preemptors to be able to update the blocking mask
745 without affecting the delivery of this signal, so we save the
746 current value to test against later. */
747 sigset_t blocked = ss->blocked;
748
749 /* Check for a preempted signal. Preempted signals can arrive during
750 critical sections. */
751 {
752 inline sighandler_t try_preemptor (struct hurd_signal_preemptor *pe)
753 { /* PE cannot be null. */
754 do
755 {
756 if (HURD_PREEMPT_SIGNAL_P (pe, signo, detail->exc_subcode))
757 {
758 if (pe->preemptor)
759 {
760 sighandler_t handler = (*pe->preemptor) (pe, ss,
761 &signo, detail);
762 if (handler != SIG_ERR)
763 return handler;
764 }
765 else
766 return pe->handler;
767 }
768 pe = pe->next;
769 } while (pe != 0);
770 return SIG_ERR;
771 }
772
773 handler = ss->preemptors ? try_preemptor (ss->preemptors) : SIG_ERR;
774
775 /* If no thread-specific preemptor, check for a global one. */
776 if (handler == SIG_ERR && __sigismember (set: &_hurdsig_preempted_set, sig: signo))
777 {
778 __mutex_lock (&_hurd_siglock);
779 handler = try_preemptor (_hurdsig_preemptors);
780 __mutex_unlock (&_hurd_siglock);
781 }
782 }
783
784 ss_suspended = 0;
785
786 if (handler == SIG_IGN)
787 /* Ignore the signal altogether. */
788 act = ignore;
789 else if (handler != SIG_ERR)
790 {
791 /* Run the preemption-provided handler. */
792 action = &preempt_sigaction;
793 act = handle;
794 }
795 else
796 {
797 /* No preemption. Do normal handling. */
798
799 action = & _hurd_sigstate_actions (ss) [signo];
800
801 if (!untraced && __sigismember (set: &_hurdsig_traced, sig: signo))
802 {
803 /* We are being traced. Stop to tell the debugger of the signal. */
804 if (_hurd_stopped)
805 /* Already stopped. Mark the signal as pending;
806 when resumed, we will notice it and stop again. */
807 mark_pending ();
808 else
809 suspend ();
810 _hurd_sigstate_unlock (ss);
811 reply ();
812 return NULL;
813 }
814
815 handler = action->sa_handler;
816
817 if (handler == SIG_DFL)
818 /* Figure out the default action for this signal. */
819 switch (signo)
820 {
821 case 0:
822 /* A sig_post msg with SIGNO==0 is sent to
823 tell us to check for pending signals. */
824 act = ignore;
825 break;
826
827 case SIGTTIN:
828 case SIGTTOU:
829 case SIGSTOP:
830 case SIGTSTP:
831 act = stop;
832 break;
833
834 case SIGCONT:
835 case SIGIO:
836 case SIGURG:
837 case SIGCHLD:
838 case SIGWINCH:
839 act = ignore;
840 break;
841
842 case SIGQUIT:
843 case SIGILL:
844 case SIGTRAP:
845 case SIGIOT:
846 case SIGEMT:
847 case SIGFPE:
848 case SIGBUS:
849 case SIGSEGV:
850 case SIGSYS:
851 act = core;
852 break;
853
854 case SIGINFO:
855 if (_hurd_pgrp == _hurd_pid)
856 {
857 /* We are the process group leader. Since there is no
858 user-specified handler for SIGINFO, we use a default one
859 which prints something interesting. We use the normal
860 handler mechanism instead of just doing it here to avoid
861 the signal thread faulting or blocking in this
862 potentially hairy operation. */
863 act = handle;
864 handler = _hurd_siginfo_handler;
865 }
866 else
867 act = ignore;
868 break;
869
870 default:
871 act = term;
872 break;
873 }
874 else if (handler == SIG_IGN)
875 act = ignore;
876 else
877 act = handle;
878
879 if (__sigmask (signo) & STOPSIGS)
880 /* Stop signals clear a pending SIGCONT even if they
881 are handled or ignored (but not if preempted). */
882 __sigdelset (set: &ss->pending, SIGCONT);
883 else
884 {
885 if (signo == SIGCONT)
886 /* Even if handled or ignored (but not preempted), SIGCONT clears
887 stop signals and resumes the process. */
888 ss->pending &= ~STOPSIGS;
889
890 if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
891 resume ();
892 }
893 }
894
895 if (_hurd_orphaned && act == stop
896 && (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU)
897 | __sigmask (SIGTSTP))))
898 {
899 /* If we would ordinarily stop for a job control signal, but we are
900 orphaned so noone would ever notice and continue us again, we just
901 quietly die, alone and in the dark. */
902 detail->code = signo;
903 signo = SIGKILL;
904 act = term;
905 }
906
907 /* Handle receipt of a blocked signal, or any signal while stopped. */
908 if (__sigismember (set: &blocked, sig: signo) || (signo != SIGKILL && _hurd_stopped))
909 {
910 mark_pending ();
911 act = ignore;
912 }
913
914 /* Perform the chosen action for the signal. */
915 switch (act)
916 {
917 case stop:
918 if (_hurd_stopped)
919 {
920 /* We are already stopped, but receiving an untraced stop
921 signal. Instead of resuming and suspending again, just
922 notify the proc server of the new stop signal. */
923 error_t err = __USEPORT (PROC, __proc_mark_stop
924 (port, signo, detail->code));
925 assert_perror (err);
926 }
927 else
928 /* Suspend the process. */
929 suspend ();
930 break;
931
932 case ignore:
933 if (detail->exc)
934 /* Blocking or ignoring a machine exception is fatal.
935 Otherwise we could just spin on the faulting instruction. */
936 goto fatal;
937
938 /* Nobody cares about this signal. If there was a call to resume
939 above in SIGCONT processing and we've left a thread suspended,
940 now's the time to set it going. */
941 if (ss_suspended)
942 {
943 assert (ss->thread != MACH_PORT_NULL);
944 err = __thread_resume (ss->thread);
945 assert_perror (err);
946 ss_suspended = 0;
947 }
948 break;
949
950 sigbomb:
951 /* We got a fault setting up the stack frame for the handler.
952 Nothing to do but die; BSD gets SIGILL in this case. */
953 detail->code = signo; /* XXX ? */
954 signo = SIGILL;
955
956 fatal:
957 act = core;
958 /* FALLTHROUGH */
959
960 case term: /* Time to die. */
961 case core: /* And leave a rotting corpse. */
962 /* Have the proc server stop all other threads in our task. */
963 err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
964 assert_perror (err);
965 /* No more user instructions will be executed.
966 The signal can now be considered delivered. */
967 reply ();
968 /* Abort all server operations now in progress. */
969 abort_all_rpcs (signo, state: &thread_state, live: 0);
970
971 {
972 int status = W_EXITCODE (0, signo);
973 /* Do a core dump if desired. Only set the wait status bit saying we
974 in fact dumped core if the operation was actually successful. */
975 if (act == core && write_corefile (signo, detail))
976 status |= WCOREFLAG;
977 /* Tell proc how we died and then stick the saber in the gut. */
978 _hurd_exit (status);
979 /* NOTREACHED */
980 }
981
982 case handle:
983 /* Call a handler for this signal. */
984 {
985 struct sigcontext *scp, ocontext;
986 int wait_for_reply, state_changed;
987
988 assert (ss->thread != MACH_PORT_NULL);
989
990 /* Stop the thread and abort its pending RPC operations. */
991 if (! ss_suspended)
992 {
993 err = __thread_suspend (ss->thread);
994 assert_perror (err);
995 }
996
997 /* Abort the thread's kernel context, so any pending message send
998 or receive completes immediately or aborts. If an interruptible
999 RPC is in progress, abort_rpcs will do this. But we must always
1000 do it before fetching the thread's state, because
1001 thread_get_state is never kosher before thread_abort. */
1002 abort_thread (ss, state: &thread_state, NULL);
1003
1004 if (ss->context)
1005 {
1006 /* We have a previous sigcontext that sigreturn was about
1007 to restore when another signal arrived. */
1008
1009 mach_port_t *loc;
1010
1011 if (_hurdsig_catch_memory_fault (ss->context))
1012 {
1013 /* We faulted reading the thread's stack. Forget that
1014 context and pretend it wasn't there. It almost
1015 certainly crash if this handler returns, but that's it's
1016 problem. */
1017 ss->context = NULL;
1018 }
1019 else
1020 {
1021 /* Copy the context from the thread's stack before
1022 we start diddling the stack to set up the handler. */
1023 ocontext = *ss->context;
1024 ss->context = &ocontext;
1025 }
1026 _hurdsig_end_catch_fault ();
1027
1028 if (! machine_get_basic_state (ss->thread, &thread_state))
1029 goto sigbomb;
1030 loc = interrupted_reply_port_location (ss->thread,
1031 &thread_state, 1);
1032 if (loc && *loc != MACH_PORT_NULL)
1033 /* This is the reply port for the context which called
1034 sigreturn. Since we are abandoning that context entirely
1035 and restoring SS->context instead, destroy this port. */
1036 __mach_port_destroy (__mach_task_self (), *loc);
1037
1038 /* The thread was in sigreturn, not in any interruptible RPC. */
1039 wait_for_reply = 0;
1040
1041 assert (! __spin_lock_locked (&ss->critical_section_lock));
1042 }
1043 else
1044 {
1045 int crit = __spin_lock_locked (&ss->critical_section_lock);
1046
1047 wait_for_reply
1048 = (_hurdsig_abort_rpcs (ss,
1049 /* In a critical section, any RPC
1050 should be cancelled instead of
1051 restarted, regardless of
1052 SA_RESTART, so the entire
1053 "atomic" operation can be aborted
1054 as a unit. */
1055 crit ? 0 : signo, 1,
1056 &thread_state, &state_changed,
1057 reply)
1058 != MACH_PORT_NULL);
1059
1060 if (crit)
1061 {
1062 /* The thread is in a critical section. Mark the signal as
1063 pending. When it finishes the critical section, it will
1064 check for pending signals. */
1065 mark_pending ();
1066 if (state_changed)
1067 /* Some cases of interrupting an RPC must change the
1068 thread state to back out the call. Normally this
1069 change is rolled into the warping to the handler and
1070 sigreturn, but we are not running the handler now
1071 because the thread is in a critical section. Instead,
1072 mutate the thread right away for the RPC interruption
1073 and resume it; the RPC will return early so the
1074 critical section can end soon. */
1075 __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
1076 (natural_t *) &thread_state.basic,
1077 MACHINE_THREAD_STATE_COUNT);
1078 /* */
1079 ss->intr_port = MACH_PORT_NULL;
1080 __thread_resume (ss->thread);
1081 break;
1082 }
1083 }
1084
1085 /* Call the machine-dependent function to set the thread up
1086 to run the signal handler, and preserve its old context. */
1087 scp = _hurd_setup_sighandler (ss, action, handler, signo, detail,
1088 rpc_wait: wait_for_reply, state: &thread_state);
1089 if (scp == NULL)
1090 goto sigbomb;
1091
1092 /* Set the machine-independent parts of the signal context. */
1093
1094 {
1095 /* Fetch the thread variable for the MiG reply port,
1096 and set it to MACH_PORT_NULL. */
1097 mach_port_t *loc = interrupted_reply_port_location (ss->thread,
1098 &thread_state,
1099 1);
1100 if (loc)
1101 {
1102 scp->sc_reply_port = *loc;
1103 *loc = MACH_PORT_NULL;
1104 }
1105 else
1106 scp->sc_reply_port = MACH_PORT_NULL;
1107
1108 /* Save the intr_port in use by the interrupted code,
1109 and clear the cell before running the trampoline. */
1110 scp->sc_intr_port = ss->intr_port;
1111 ss->intr_port = MACH_PORT_NULL;
1112
1113 if (ss->context)
1114 {
1115 /* After the handler runs we will restore to the state in
1116 SS->context, not the state of the thread now. So restore
1117 that context's reply port and intr port. */
1118
1119 scp->sc_reply_port = ss->context->sc_reply_port;
1120 scp->sc_intr_port = ss->context->sc_intr_port;
1121
1122 ss->context = NULL;
1123 }
1124 }
1125
1126 /* Backdoor extra argument to signal handler. */
1127 scp->sc_error = detail->error;
1128
1129 /* Block requested signals while running the handler. */
1130 scp->sc_mask = ss->blocked;
1131 __sigorset (dest: &ss->blocked, left: &ss->blocked, right: &action->sa_mask);
1132
1133 /* Also block SIGNO unless we're asked not to. */
1134 if (! (action->sa_flags & (SA_RESETHAND | SA_NODEFER)))
1135 __sigaddset (set: &ss->blocked, sig: signo);
1136
1137 /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot
1138 be automatically reset when delivered; the system silently
1139 enforces this restriction. */
1140 if (action->sa_flags & SA_RESETHAND
1141 && signo != SIGILL && signo != SIGTRAP)
1142 action->sa_handler = SIG_DFL;
1143
1144 /* Any sigsuspend call must return after the handler does. */
1145 wake_sigsuspend (ss);
1146
1147 /* Start the thread running the handler (or possibly waiting for an
1148 RPC reply before running the handler). */
1149 err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
1150 (natural_t *) &thread_state.basic,
1151 MACHINE_THREAD_STATE_COUNT);
1152 assert_perror (err);
1153 err = __thread_resume (ss->thread);
1154 assert_perror (err);
1155 thread_state.set = 0; /* Everything we know is now wrong. */
1156 break;
1157 }
1158 }
1159
1160 return ss;
1161}
1162
1163/* Return the set of pending signals in SS which should be delivered. */
1164static sigset_t
1165pending_signals (struct hurd_sigstate *ss)
1166{
1167 /* We don't worry about any pending signals if we are stopped, nor if
1168 SS is in a critical section. We are guaranteed to get a sig_post
1169 message before any of them become deliverable: either the SIGCONT
1170 signal, or a sig_post with SIGNO==0 as an explicit poll when the
1171 thread finishes its critical section. */
1172 if (_hurd_stopped || __spin_lock_locked (&ss->critical_section_lock))
1173 return 0;
1174
1175 return _hurd_sigstate_pending (ss) & ~ss->blocked;
1176}
1177
1178/* Post the specified pending signals in SS and return 1. If one of
1179 them is traced, abort immediately and return 0. SS must be locked on
1180 entry and will be unlocked in all cases. */
1181static int
1182post_pending (struct hurd_sigstate *ss, sigset_t pending, void (*reply) (void))
1183{
1184 int signo;
1185 struct hurd_signal_detail detail;
1186
1187 /* Make sure SS corresponds to an actual thread, since we assume it won't
1188 change in post_signal. */
1189 assert (ss->thread != MACH_PORT_NULL);
1190
1191 for (signo = 1; signo < NSIG; ++signo)
1192 if (__sigismember (set: &pending, sig: signo))
1193 {
1194 detail = sigstate_clear_pending (ss, signo);
1195 _hurd_sigstate_unlock (ss);
1196
1197 /* Will reacquire the lock, except if the signal is traced. */
1198 if (! post_signal (ss, signo, detail: &detail, untraced: 0, reply))
1199 return 0;
1200 }
1201
1202 /* No more signals pending; SS->lock is still locked. */
1203 _hurd_sigstate_unlock (ss);
1204
1205 return 1;
1206}
1207
1208/* Post all the pending signals of all threads and return 1. If a traced
1209 signal is encountered, abort immediately and return 0. */
1210static int
1211post_all_pending_signals (void (*reply) (void))
1212{
1213 struct hurd_sigstate *ss;
1214 sigset_t pending = 0;
1215
1216 for (;;)
1217 {
1218 __mutex_lock (&_hurd_siglock);
1219 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
1220 {
1221 _hurd_sigstate_lock (ss);
1222
1223 pending = pending_signals (ss);
1224 if (pending)
1225 /* post_pending() below will unlock SS. */
1226 break;
1227
1228 _hurd_sigstate_unlock (ss);
1229 }
1230 __mutex_unlock (&_hurd_siglock);
1231
1232 if (! pending)
1233 return 1;
1234 if (! post_pending (ss, pending, reply))
1235 return 0;
1236 }
1237}
1238
1239/* Deliver a signal. SS is not locked. */
1240void
1241_hurd_internal_post_signal (struct hurd_sigstate *ss,
1242 int signo, struct hurd_signal_detail *detail,
1243 mach_port_t reply_port,
1244 mach_msg_type_name_t reply_port_type,
1245 int untraced)
1246{
1247 /* Reply to this sig_post message. */
1248 __typeof (__msg_sig_post_reply) *reply_rpc
1249 = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply);
1250 void reply (void)
1251 {
1252 error_t err;
1253 if (reply_port == MACH_PORT_NULL)
1254 return;
1255 err = (*reply_rpc) (reply_port, reply_port_type, 0);
1256 reply_port = MACH_PORT_NULL;
1257 if (err != MACH_SEND_INVALID_DEST) /* Ignore dead reply port. */
1258 assert_perror (err);
1259 }
1260
1261 ss = post_signal (ss, signo, detail, untraced, reply);
1262 if (! ss)
1263 return;
1264
1265 /* The signal was neither fatal nor traced. We still hold SS->lock. */
1266 if (signo != 0 && ss->thread != MACH_PORT_NULL)
1267 {
1268 /* The signal has either been ignored or is now being handled. We can
1269 consider it delivered and reply to the killer. */
1270 reply ();
1271
1272 /* Post any pending signals for this thread. */
1273 if (! post_pending (ss, pending: pending_signals (ss), reply))
1274 return;
1275 }
1276 else
1277 {
1278 /* If this was a process-wide signal or a poll request, we need
1279 to check for pending signals for all threads. */
1280 _hurd_sigstate_unlock (ss);
1281 if (! post_all_pending_signals (reply))
1282 return;
1283
1284 /* All pending signals delivered to all threads.
1285 Now we can send the reply message even for signal 0. */
1286 reply ();
1287 }
1288}
1289
1290/* Decide whether REFPORT enables the sender to send us a SIGNO signal.
1291 Returns zero if so, otherwise the error code to return to the sender. */
1292
1293static error_t
1294signal_allowed (int signo, mach_port_t refport)
1295{
1296 if (signo < 0 || signo >= NSIG)
1297 return EINVAL;
1298
1299 if (refport == __mach_task_self ())
1300 /* Can send any signal. */
1301 goto win;
1302
1303 /* Avoid needing to check for this below. */
1304 if (refport == MACH_PORT_NULL)
1305 return EPERM;
1306
1307 switch (signo)
1308 {
1309 case SIGINT:
1310 case SIGQUIT:
1311 case SIGTSTP:
1312 case SIGHUP:
1313 case SIGINFO:
1314 case SIGTTIN:
1315 case SIGTTOU:
1316 case SIGWINCH:
1317 /* Job control signals can be sent by the controlling terminal. */
1318 if (__USEPORT (CTTYID, port == refport))
1319 goto win;
1320 break;
1321
1322 case SIGCONT:
1323 {
1324 /* A continue signal can be sent by anyone in the session. */
1325 mach_port_t sessport;
1326 if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
1327 {
1328 __mach_port_deallocate (__mach_task_self (), sessport);
1329 if (refport == sessport)
1330 goto win;
1331 }
1332 }
1333 break;
1334
1335 case SIGIO:
1336 case SIGURG:
1337 {
1338 /* Any io object a file descriptor refers to might send us
1339 one of these signals using its async ID port for REFPORT.
1340
1341 This is pretty wide open; it is not unlikely that some random
1342 process can at least open for reading something we have open,
1343 get its async ID port, and send us a spurious SIGIO or SIGURG
1344 signal. But BSD is actually wider open than that!--you can set
1345 the owner of an io object to any process or process group
1346 whatsoever and send them gratuitous signals.
1347
1348 Someday we could implement some reasonable scheme for
1349 authorizing SIGIO and SIGURG signals properly. */
1350
1351 int d;
1352 int lucky = 0; /* True if we find a match for REFPORT. */
1353 __mutex_lock (&_hurd_dtable_lock);
1354 for (d = 0; !lucky && (unsigned) d < (unsigned) _hurd_dtablesize; ++d)
1355 {
1356 struct hurd_userlink ulink;
1357 io_t port;
1358 mach_port_t asyncid;
1359 if (_hurd_dtable[d] == NULL)
1360 continue;
1361 port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
1362 if (! __io_get_icky_async_id (port, &asyncid))
1363 {
1364 if (refport == asyncid)
1365 /* Break out of the loop on the next iteration. */
1366 lucky = 1;
1367 __mach_port_deallocate (__mach_task_self (), asyncid);
1368 }
1369 _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
1370 }
1371 __mutex_unlock (&_hurd_dtable_lock);
1372 /* If we found a lucky winner, we've set D to -1 in the loop. */
1373 if (lucky)
1374 goto win;
1375 }
1376 }
1377
1378 /* If this signal is legit, we have done `goto win' by now.
1379 When we return the error, mig deallocates REFPORT. */
1380 return EPERM;
1381
1382 win:
1383 /* Deallocate the REFPORT send right; we are done with it. */
1384 __mach_port_deallocate (__mach_task_self (), refport);
1385
1386 return 0;
1387}
1388
1389/* Implement the sig_post RPC from <hurd/msg.defs>;
1390 sent when someone wants us to get a signal. */
1391kern_return_t
1392_S_msg_sig_post (mach_port_t me,
1393 mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
1394 int signo, natural_t sigcode,
1395 mach_port_t refport)
1396{
1397 error_t err;
1398 struct hurd_signal_detail d;
1399
1400 if (err = signal_allowed (signo, refport))
1401 return err;
1402
1403 d.code = d.exc_subcode = sigcode;
1404 d.exc = 0;
1405
1406 /* Post the signal to a global receiver thread (or mark it pending in
1407 the global sigstate). This will reply when the signal can be
1408 considered delivered. */
1409 _hurd_internal_post_signal (_hurd_global_sigstate,
1410 signo, &d, reply_port, reply_port_type,
1411 0); /* Stop if traced. */
1412
1413 return MIG_NO_REPLY; /* Already replied. */
1414}
1415
1416/* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1417 sent when the debugger wants us to really get a signal
1418 even if we are traced. */
1419kern_return_t
1420_S_msg_sig_post_untraced (mach_port_t me,
1421 mach_port_t reply_port,
1422 mach_msg_type_name_t reply_port_type,
1423 int signo, natural_t sigcode,
1424 mach_port_t refport)
1425{
1426 error_t err;
1427 struct hurd_signal_detail d;
1428
1429 if (err = signal_allowed (signo, refport))
1430 return err;
1431
1432 d.code = d.exc_subcode = sigcode;
1433 d.exc = 0;
1434
1435 /* Post the signal to the designated signal-receiving thread. This will
1436 reply when the signal can be considered delivered. */
1437 _hurd_internal_post_signal (_hurd_global_sigstate,
1438 signo, &d, reply_port, reply_port_type,
1439 1); /* Untraced flag. */
1440
1441 return MIG_NO_REPLY; /* Already replied. */
1442}
1443
1444extern void __mig_init (void *);
1445
1446#include <mach/task_special_ports.h>
1447
1448/* Initialize the message port, _hurd_global_sigstate, and start the
1449 signal thread. */
1450
1451void
1452_hurdsig_init (const int *intarray, size_t intarraysize)
1453{
1454 error_t err;
1455 vm_size_t stacksize;
1456 struct hurd_sigstate *ss;
1457
1458 __mutex_init (&_hurd_siglock);
1459
1460 err = __mach_port_allocate (__mach_task_self (),
1461 MACH_PORT_RIGHT_RECEIVE,
1462 &_hurd_msgport);
1463 assert_perror (err);
1464
1465 /* Make a send right to the signal port. */
1466 err = __mach_port_insert_right (__mach_task_self (),
1467 _hurd_msgport,
1468 _hurd_msgport,
1469 MACH_MSG_TYPE_MAKE_SEND);
1470 assert_perror (err);
1471
1472 /* Initialize the global signal state. */
1473 _hurd_global_sigstate = _hurd_thread_sigstate (MACH_PORT_NULL);
1474
1475 /* We block all signals, and let actual threads pull them from the
1476 pending mask. */
1477 __sigfillset(set: & _hurd_global_sigstate->blocked);
1478
1479 /* Initialize the main thread's signal state. */
1480 ss = _hurd_self_sigstate ();
1481
1482 /* Mark it as a process-wide signal receiver. Threads in this set use
1483 the common action vector in _hurd_global_sigstate. */
1484 _hurd_sigstate_set_global_rcv (ss);
1485
1486 /* Copy inherited signal settings from our parent (or pre-exec process
1487 state) */
1488 if (intarraysize > INIT_SIGMASK)
1489 ss->blocked = intarray[INIT_SIGMASK];
1490 if (intarraysize > INIT_SIGPENDING)
1491 _hurd_global_sigstate->pending = intarray[INIT_SIGPENDING];
1492 if (intarraysize > INIT_SIGIGN && intarray[INIT_SIGIGN] != 0)
1493 {
1494 int signo;
1495 for (signo = 1; signo < NSIG; ++signo)
1496 if (intarray[INIT_SIGIGN] & __sigmask(signo))
1497 _hurd_global_sigstate->actions[signo].sa_handler = SIG_IGN;
1498 }
1499
1500 /* Start the signal thread listening on the message port. */
1501
1502#pragma weak __pthread_create
1503 if (!__pthread_create)
1504 {
1505 err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
1506 assert_perror (err);
1507
1508 stacksize = __vm_page_size * 8; /* Small stack for signal thread. */
1509 err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1510 _hurd_msgport_receive,
1511 (vm_address_t *) &__hurd_sigthread_stack_base,
1512 &stacksize);
1513 assert_perror (err);
1514 err = __mach_setup_tls (_hurd_msgport_thread);
1515 assert_perror (err);
1516
1517 __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1518
1519 /* Reinitialize the MiG support routines so they will use a per-thread
1520 variable for the cached reply port. */
1521 __mig_init ((void *) __hurd_sigthread_stack_base);
1522
1523 err = __thread_resume (_hurd_msgport_thread);
1524 assert_perror (err);
1525 }
1526 else
1527 {
1528 pthread_t thread;
1529 pthread_attr_t attr;
1530 void *addr;
1531 size_t size;
1532
1533 /* When pthread is being used, we need to make the signal thread a
1534 proper pthread. Otherwise it cannot use mutex_lock et al, which
1535 will be the pthread versions. Various of the message port RPC
1536 handlers need to take locks, so we need to be able to call into
1537 pthread code and meet its assumptions about how our thread and
1538 its stack are arranged. Since pthread puts it there anyway,
1539 we'll let the signal thread's per-thread variables be found as for
1540 any normal pthread, and just leave the magic __hurd_sigthread_*
1541 values all zero so they'll be ignored. */
1542
1543#pragma weak __pthread_detach
1544#pragma weak __pthread_getattr_np
1545#pragma weak __pthread_attr_getstack
1546 __pthread_create(newthread: &thread, NULL, start_routine: &_hurd_msgport_receive, NULL);
1547
1548 /* Record signal thread stack layout for fork() */
1549 __pthread_getattr_np (thread, &attr);
1550 __pthread_attr_getstack (attr: &attr, stackaddr: &addr, stacksize: &size);
1551 __hurd_sigthread_stack_base = (uintptr_t) addr;
1552 __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + size;
1553
1554 __pthread_detach(th: thread);
1555
1556 /* XXX We need the thread port for the signal thread further on
1557 in this thread (see hurdfault.c:_hurdsigfault_init).
1558 Therefore we block until _hurd_msgport_thread is initialized
1559 by the newly created thread. This really shouldn't be
1560 necessary; we should be able to fetch the thread port for a
1561 pthread from here. */
1562 while (_hurd_msgport_thread == 0)
1563 __swtch_pri (0);
1564 }
1565
1566 /* Receive exceptions on the signal port. */
1567#ifdef TASK_EXCEPTION_PORT
1568 __task_set_special_port (__mach_task_self (),
1569 TASK_EXCEPTION_PORT, _hurd_msgport);
1570#elif defined (EXC_MASK_ALL)
1571 __task_set_exception_ports (__mach_task_self (),
1572 EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
1573 | EXC_MASK_MACH_SYSCALL
1574 | EXC_MASK_RPC_ALERT),
1575 _hurd_msgport,
1576 EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
1577#else
1578# error task_set_exception_port?
1579#endif
1580
1581 /* Sanity check. Any pending, unblocked signals should have been
1582 taken by our predecessor incarnation (i.e. parent or pre-exec state)
1583 before packing up our init ints. This assert is last (not above)
1584 so that signal handling is all set up to handle the abort. */
1585 assert ((ss->pending &~ ss->blocked) == 0);
1586}
1587 /* XXXX */
1588/* Reauthenticate with the proc server. */
1589
1590static void
1591reauth_proc (mach_port_t new)
1592{
1593 mach_port_t ref, ignore;
1594
1595 ref = __mach_reply_port ();
1596 if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1597 __proc_reauthenticate (port, ref,
1598 MACH_MSG_TYPE_MAKE_SEND)
1599 || __auth_user_authenticate (new, ref,
1600 MACH_MSG_TYPE_MAKE_SEND,
1601 &ignore))
1602 && ignore != MACH_PORT_NULL)
1603 __mach_port_deallocate (__mach_task_self (), ignore);
1604 __mach_port_destroy (__mach_task_self (), ref);
1605
1606 /* Set the owner of the process here too. */
1607 __mutex_lock (&_hurd_id.lock);
1608 if (!_hurd_check_ids ())
1609 HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1610 __proc_setowner (port,
1611 (_hurd_id.gen.nuids
1612 ? _hurd_id.gen.uids[0] : 0),
1613 !_hurd_id.gen.nuids));
1614 __mutex_unlock (&_hurd_id.lock);
1615
1616 (void) &reauth_proc; /* Silence compiler warning. */
1617}
1618text_set_element (_hurd_reauth_hook, reauth_proc);
1619
1620/* Like `getenv', but safe for the signal thread to run.
1621 If the environment is trashed, this will just return NULL. */
1622
1623const char *
1624_hurdsig_getenv (const char *variable)
1625{
1626 if (__libc_enable_secure)
1627 return NULL;
1628
1629 if (_hurdsig_catch_memory_fault (__environ))
1630 /* We bombed in getenv. */
1631 return NULL;
1632 else
1633 {
1634 const size_t len = strlen (s: variable);
1635 char *value = NULL;
1636 char *volatile *ep = __environ;
1637 while (*ep)
1638 {
1639 const char *p = *ep;
1640 _hurdsig_fault_preemptor.first = (long int) p;
1641 _hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
1642 if (! strncmp (s1: p, s2: variable, n: len) && p[len] == '=')
1643 {
1644 size_t valuelen;
1645 p += len + 1;
1646 valuelen = strlen (s: p);
1647 _hurdsig_fault_preemptor.last = (long int) (p + valuelen);
1648 value = malloc (++valuelen);
1649 if (value)
1650 memcpy (dest: value, src: p, n: valuelen);
1651 break;
1652 }
1653 _hurdsig_fault_preemptor.first = (long int) ++ep;
1654 _hurdsig_fault_preemptor.last = (long int) (ep + 1);
1655 }
1656 _hurdsig_end_catch_fault ();
1657 return value;
1658 }
1659}
1660

source code of glibc/hurd/hurdsig.c