]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/hurdsig.c
Update copyright dates with scripts/update-copyrights
[thirdparty/glibc.git] / hurd / hurdsig.c
CommitLineData
2b778ceb 1/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
2c6fe0bd 2 This file is part of the GNU C Library.
28f540f4 3
2c6fe0bd 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
28f540f4 8
2c6fe0bd
UD
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
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
28f540f4 17
28f540f4 18#include <stdio.h>
64659255 19#include <stdlib.h>
28f540f4 20#include <string.h>
64659255 21
9446e02b 22#include <lock-intern.h> /* For `struct mutex'. */
0f652f05 23#include <pthreadP.h>
64659255
MK
24#include <mach.h>
25#include <mach/thread_switch.h>
7a8f45e3 26#include <mach/mig_support.h>
9446e02b 27#include <mach/vm_param.h>
64659255
MK
28
29#include <hurd.h>
762a2918 30#include <hurd/id.h>
64659255
MK
31#include <hurd/signal.h>
32
28f540f4
RM
33#include "hurdfault.h"
34#include "hurdmalloc.h" /* XXX */
cc13edc8 35#include "../locale/localeinfo.h"
28f540f4 36
e8ef51b1
ST
37#include <libc-diag.h>
38
28f540f4
RM
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
6bac11d9
MB
50/* These are set up by _hurdsig_init. */
51unsigned long int __hurd_sigthread_stack_base;
52unsigned long int __hurd_sigthread_stack_end;
6bac11d9 53
28f540f4
RM
54/* Linked-list of per-thread signal state. */
55struct hurd_sigstate *_hurd_sigstates;
54da5be3 56
653d74f1
JK
57/* Sigstate for the task-global signals. */
58struct hurd_sigstate *_hurd_global_sigstate;
59
54da5be3 60/* Timeout for RPC's after interrupt_operation. */
46a7f24c 61mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 60000;
28f540f4
RM
62\f
63static void
64default_sigaction (struct sigaction actions[NSIG])
65{
66 int signo;
67
68 __sigemptyset (&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)
b96bdcd7 83 break;
28f540f4
RM
84 if (ss == NULL)
85 {
86 ss = malloc (sizeof (*ss));
87 if (ss == NULL)
653d74f1 88 __libc_fatal ("hurd: Can't allocate sigstate\n");
61416e19 89 __spin_lock_init (&ss->critical_section_lock);
28f540f4 90 __spin_lock_init (&ss->lock);
61416e19 91 ss->thread = thread;
28f540f4 92
6df1b247 93 /* Initialize default state. */
28f540f4
RM
94 __sigemptyset (&ss->blocked);
95 __sigemptyset (&ss->pending);
96 memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
a0bb5abd 97 ss->sigaltstack.ss_flags |= SS_DISABLE;
10dc2a90 98 ss->preemptors = NULL;
e8bceaee 99 ss->suspended = MACH_PORT_NULL;
28f540f4
RM
100 ss->intr_port = MACH_PORT_NULL;
101 ss->context = NULL;
61416e19
ST
102 ss->active_resources = NULL;
103 ss->cancel = 0;
104 ss->cancel_hook = NULL;
28f540f4 105
653d74f1
JK
106 if (thread == MACH_PORT_NULL)
107 {
108 /* Process-wide sigstate, use the system defaults. */
109 default_sigaction (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 }
28f540f4
RM
115 else
116 {
5c06743c
RB
117 error_t err;
118
653d74f1
JK
119 /* Use the global actions as a default for new threads. */
120 struct hurd_sigstate *s = _hurd_global_sigstate;
28f540f4
RM
121 if (s)
122 {
123 __spin_lock (&s->lock);
124 memcpy (ss->actions, s->actions, sizeof (s->actions));
125 __spin_unlock (&s->lock);
126 }
127 else
128 default_sigaction (ss->actions);
28f540f4 129
653d74f1
JK
130 ss->next = _hurd_sigstates;
131 _hurd_sigstates = ss;
5c06743c
RB
132
133 err = __mach_port_mod_refs (__mach_task_self (), thread,
134 MACH_PORT_RIGHT_SEND, 1);
135 if (err)
136 __libc_fatal ("hurd: Can't add reference on Mach thread\n");
653d74f1 137 }
28f540f4
RM
138 }
139 __mutex_unlock (&_hurd_siglock);
140 return ss;
141}
7a8f45e3 142libc_hidden_def (_hurd_thread_sigstate)
653d74f1
JK
143
144/* Destroy a sigstate structure. Called by libpthread just before the
5c06743c 145 * corresponding thread is terminated. */
653d74f1
JK
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)
5c06743c
RB
162 {
163 if (ss->thread != MACH_PORT_NULL)
164 __mach_port_deallocate (__mach_task_self (), ss->thread);
165
166 free (ss);
167 }
653d74f1
JK
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 (&pending, &pending, &_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 (&_hurd_global_sigstate->pending, signo))
224 {
225 __sigdelset (&_hurd_global_sigstate->pending, signo);
226 return _hurd_global_sigstate->pending_data[signo];
227 }
228
229 assert (__sigismember (&ss->pending, signo));
230 __sigdelset (&ss->pending, 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
28f540f4
RM
247\f
248/* Signal delivery itself is on this page. */
249
250#include <hurd/fd.h>
9fd18b6c 251#include <hurd/crash.h>
79c236ac 252#include <hurd/resource.h>
28f540f4
RM
253#include <hurd/paths.h>
254#include <setjmp.h>
255#include <fcntl.h>
256#include <sys/wait.h>
8f480b4b 257#include <thread_state.h>
28f540f4
RM
258#include <hurd/msg_server.h>
259#include <hurd/msg_reply.h> /* For __msg_sig_post_reply. */
28f540f4 260#include <hurd/interrupt.h>
fb8e70d6
RM
261#include <assert.h>
262#include <unistd.h>
28f540f4 263
28f540f4 264
9fd18b6c 265/* Call the crash dump server to mummify us before we die.
28f540f4
RM
266 Returns nonzero if a core file was written. */
267static int
0e3426bb 268write_corefile (int signo, const struct hurd_signal_detail *detail)
28f540f4
RM
269{
270 error_t err;
271 mach_port_t coreserver;
272 file_t file, coredir;
273 const char *name;
274
79c236ac
RM
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
28f540f4
RM
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;
9fd18b6c 291 name = _hurdsig_getenv ("CRASHSERVER");
28f540f4
RM
292 if (name != NULL)
293 coreserver = __file_name_lookup (name, 0, 0);
294 if (coreserver == MACH_PORT_NULL)
9fd18b6c 295 coreserver = __file_name_lookup (_SERVERS_CRASH, 0, 0);
28f540f4
RM
296 if (coreserver == MACH_PORT_NULL)
297 return 0;
298
299 /* Get a port to the directory where the new core file will reside. */
78abf563 300 file = MACH_PORT_NULL;
28f540f4
RM
301 name = _hurdsig_getenv ("COREFILE");
302 if (name == NULL)
303 name = "core";
304 coredir = __file_name_split (name, (char **) &name);
78abf563
TBB
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 ? */
0f110f41 309 &file);
28f540f4
RM
310
311 /* Call the core dumping server to write the core file. */
9fd18b6c
RM
312 err = __crash_dump_task (coreserver,
313 __mach_task_self (),
0e3426bb
RM
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);
28f540f4 319 __mach_port_deallocate (__mach_task_self (), coreserver);
78abf563
TBB
320
321 if (! err && file != MACH_PORT_NULL)
28f540f4
RM
322 /* The core dump into FILE succeeded, so now link it into the
323 directory. */
70481be8 324 err = __dir_link (coredir, file, name, 1);
28f540f4
RM
325 __mach_port_deallocate (__mach_task_self (), file);
326 __mach_port_deallocate (__mach_task_self (), coredir);
78abf563 327 return !err && file != MACH_PORT_NULL;
28f540f4
RM
328}
329
330
28f540f4
RM
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
1a3a58fd 336/* SS->thread is suspended. Abort the thread and get its basic state. */
28f540f4
RM
337static void
338abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
1a3a58fd 339 void (*reply) (void))
28f540f4 340{
653d74f1
JK
341 assert (ss->thread != MACH_PORT_NULL);
342
28f540f4
RM
343 if (!(state->set & THREAD_ABORTED))
344 {
b96bdcd7
RM
345 error_t err = __thread_abort (ss->thread);
346 assert_perror (err);
28f540f4
RM
347 /* Clear all thread state flavor set bits, because thread_abort may
348 have changed the state. */
349 state->set = THREAD_ABORTED;
350 }
351
1a3a58fd
RM
352 if (reply)
353 (*reply) ();
28f540f4
RM
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
54da5be3
RM
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. */
28f540f4
RM
361
362static mach_port_t *
dc33bef3
ST
363interrupted_reply_port_location (thread_t thread,
364 struct machine_thread_all_state *thread_state,
54da5be3 365 int sigthread)
28f540f4 366{
dc33bef3 367 mach_port_t *portloc = &THREAD_TCB(thread, thread_state)->reply_port;
28f540f4 368
fb8e70d6 369 if (sigthread && _hurdsig_catch_memory_fault (portloc))
dc33bef3 370 /* Faulted trying to read the TCB. */
fb8e70d6 371 return NULL;
28f540f4 372
e8ef51b1
ST
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");
28f540f4
RM
378 /* Fault now if this pointer is bogus. */
379 *(volatile mach_port_t *) portloc = *portloc;
e8ef51b1 380 DIAG_POP_NEEDS_COMMENT;
28f540f4 381
54da5be3
RM
382 if (sigthread)
383 _hurdsig_end_catch_fault ();
28f540f4
RM
384
385 return portloc;
386}
3fe9de0d 387\f
6df1b247 388#include <hurd/sigpreempt.h>
8f480b4b 389#include <intr-msg.h>
28f540f4 390
d3dc731b
MB
391/* Timeout on interrupt_operation calls. */
392mach_msg_timeout_t _hurdsig_interrupt_timeout = 1000;
393
28f540f4
RM
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
75914335
RM
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
28f540f4
RM
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
191abc51 412mach_port_t
75914335 413_hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
54da5be3 414 struct machine_thread_all_state *state, int *state_change,
1a3a58fd 415 void (*reply) (void))
28f540f4 416{
5c81be53 417 extern const void _hurd_intr_rpc_msg_about_to;
3fe9de0d 418 extern const void _hurd_intr_rpc_msg_in_trap;
54da5be3 419 mach_port_t rcv_port = MACH_PORT_NULL;
28f540f4
RM
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. */
1a3a58fd 431 abort_thread (ss, state, reply);
28f540f4 432
34a5a146
JM
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)
28f540f4 435 {
54da5be3
RM
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. */
3fe9de0d 439 INTR_MSG_BACK_OUT (&state->basic);
54da5be3
RM
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;
28f540f4 444 }
34a5a146 445 else if (state->basic.PC == (natural_t) &_hurd_intr_rpc_msg_in_trap
54da5be3
RM
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. */
34a5a146 449 && state->basic.SYSRETURN == MACH_RCV_INTERRUPTED)
54da5be3
RM
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
dc33bef3
ST
460 mach_port_t *reply = interrupted_reply_port_location (ss->thread,
461 state,
54da5be3 462 sigthread);
d3dc731b 463 error_t err = __interrupt_operation (intr_port, _hurdsig_interrupt_timeout);
54da5be3
RM
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 }
28f540f4 474
54da5be3
RM
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. */
653d74f1 491 if (! signo || !(_hurd_sigstate_actions (ss) [signo].sa_flags & SA_RESTART))
54da5be3
RM
492 ss->intr_port = MACH_PORT_NULL;
493 }
28f540f4 494
54da5be3 495 return rcv_port;
28f540f4
RM
496}
497
54da5be3 498
28f540f4
RM
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;
fb8e70d6 525 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, ++nthreads)
28f540f4 526 if (ss->thread == _hurd_msgport_thread)
fb8e70d6 527 reply_ports[nthreads] = MACH_PORT_NULL;
28f540f4
RM
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. */
fb8e70d6
RM
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 }
28f540f4
RM
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;
54da5be3 564 err = __mach_msg (&head, MACH_RCV_MSG|MACH_RCV_TIMEOUT, 0, sizeof head,
28f540f4 565 reply_ports[nthreads],
54da5be3
RM
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 }
28f540f4
RM
576 }
577}
578
f9011787
ST
579/* Wake up any sigsuspend or pselect call that is blocking SS->thread. SS must
580 be locked. */
4288c548
JK
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
43b0e40f 603struct hurd_signal_preemptor *_hurdsig_preemptors = 0;
6df1b247 604sigset_t _hurdsig_preempted_set;
28f540f4 605
6bac11d9
MB
606/* XXX temporary to deal with spelling fix */
607weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
608
28f540f4 609/* Mask of stop signals. */
a9175662
FW
610#define STOPSIGS (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) \
611 | __sigmask (SIGSTOP) | __sigmask (SIGTSTP))
28f540f4 612
4288c548 613/* Actual delivery of a single signal. Called with SS unlocked. When
653d74f1
JK
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 *
4288c548
JK
619post_signal (struct hurd_sigstate *ss,
620 int signo, struct hurd_signal_detail *detail,
621 int untraced, void (*reply) (void))
28f540f4
RM
622{
623 struct machine_thread_all_state thread_state;
624 enum { stop, ignore, core, term, handle } act;
28f540f4
RM
625 int ss_suspended;
626
e42efa01
ST
627 /* sigaction for preemptors */
628 struct sigaction preempt_sigaction = {
629 .sa_flags = SA_RESTART
630 };
631
632 struct sigaction *action;
633
28f540f4
RM
634 /* Mark the signal as pending. */
635 void mark_pending (void)
636 {
637 __sigaddset (&ss->pending, signo);
93a470c7 638 /* Save the details to be given to the handler when SIGNO is
28f540f4 639 unblocked. */
93a470c7 640 ss->pending_data[signo] = *detail;
28f540f4
RM
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);
6a7169a5 655 reply ();
0e3426bb 656 __proc_mark_stop (port, signo, detail->code);
28f540f4
RM
657 }));
658 _hurd_stopped = 1;
659 }
75914335
RM
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 {
653d74f1
JK
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)
75914335
RM
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;
75914335
RM
696 }
697
4288c548
JK
698 error_t err;
699 sighandler_t handler;
700
75914335
RM
701 if (signo == 0)
702 {
703 if (untraced)
4288c548
JK
704 {
705 /* This is PTRACE_CONTINUE. */
706 act = ignore;
707 resume ();
708 }
75914335
RM
709
710 /* This call is just to check for pending signals. */
653d74f1
JK
711 _hurd_sigstate_lock (ss);
712 return ss;
75914335 713 }
28f540f4 714
28f540f4
RM
715 thread_state.set = 0; /* We know nothing. */
716
653d74f1
JK
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 (rss))
730 continue;
731
732 /* The global sigstate is already locked. */
733 __spin_lock (&rss->lock);
734 if (! __sigismember (&rss->blocked, 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;
28f540f4 748
6df1b247
RM
749 /* Check for a preempted signal. Preempted signals can arrive during
750 critical sections. */
e26996aa
RM
751 {
752 inline sighandler_t try_preemptor (struct hurd_signal_preemptor *pe)
753 { /* PE cannot be null. */
754 do
755 {
d865ff74 756 if (HURD_PREEMPT_SIGNAL_P (pe, signo, detail->exc_subcode))
e26996aa
RM
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 }
6df1b247 772
e26996aa 773 handler = ss->preemptors ? try_preemptor (ss->preemptors) : SIG_ERR;
6df1b247 774
e26996aa 775 /* If no thread-specific preemptor, check for a global one. */
044edf6d 776 if (handler == SIG_ERR && __sigismember (&_hurdsig_preempted_set, signo))
e26996aa
RM
777 {
778 __mutex_lock (&_hurd_siglock);
779 handler = try_preemptor (_hurdsig_preemptors);
780 __mutex_unlock (&_hurd_siglock);
781 }
782 }
28f540f4
RM
783
784 ss_suspended = 0;
785
6df1b247
RM
786 if (handler == SIG_IGN)
787 /* Ignore the signal altogether. */
788 act = ignore;
09d434df 789 else if (handler != SIG_ERR)
e42efa01
ST
790 {
791 /* Run the preemption-provided handler. */
792 action = &preempt_sigaction;
793 act = handle;
794 }
28f540f4
RM
795 else
796 {
797 /* No preemption. Do normal handling. */
798
e42efa01
ST
799 action = & _hurd_sigstate_actions (ss) [signo];
800
8f0c527e 801 if (!untraced && __sigismember (&_hurdsig_traced, signo))
28f540f4
RM
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 ();
653d74f1 810 _hurd_sigstate_unlock (ss);
28f540f4 811 reply ();
653d74f1 812 return NULL;
28f540f4
RM
813 }
814
e42efa01 815 handler = action->sa_handler;
75914335 816
28f540f4
RM
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). */
05dea6d1 882 __sigdelset (&ss->pending, SIGCONT);
28f540f4
RM
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))
75914335 891 resume ();
28f540f4
RM
892 }
893 }
894
a04549c1
JM
895 if (_hurd_orphaned && act == stop
896 && (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU)
897 | __sigmask (SIGTSTP))))
28f540f4
RM
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. */
0e3426bb 902 detail->code = signo;
28f540f4
RM
903 signo = SIGKILL;
904 act = term;
905 }
906
75914335 907 /* Handle receipt of a blocked signal, or any signal while stopped. */
653d74f1 908 if (__sigismember (&blocked, signo) || (signo != SIGKILL && _hurd_stopped))
28f540f4
RM
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)
b96bdcd7
RM
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. */
0e3426bb
RM
923 error_t err = __USEPORT (PROC, __proc_mark_stop
924 (port, signo, detail->code));
b96bdcd7
RM
925 assert_perror (err);
926 }
28f540f4
RM
927 else
928 /* Suspend the process. */
929 suspend ();
930 break;
931
932 case ignore:
2b965f1b
RM
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
4d02a5b1
RM
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 {
653d74f1 943 assert (ss->thread != MACH_PORT_NULL);
4d02a5b1
RM
944 err = __thread_resume (ss->thread);
945 assert_perror (err);
946 ss_suspended = 0;
947 }
28f540f4
RM
948 break;
949
421f82e5
RM
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. */
0e3426bb 953 detail->code = signo; /* XXX ? */
421f82e5 954 signo = SIGILL;
2b965f1b
RM
955
956 fatal:
421f82e5
RM
957 act = core;
958 /* FALLTHROUGH */
959
28f540f4
RM
960 case term: /* Time to die. */
961 case core: /* And leave a rotting corpse. */
28f540f4 962 /* Have the proc server stop all other threads in our task. */
b96bdcd7
RM
963 err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
964 assert_perror (err);
28f540f4
RM
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, &thread_state, 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. */
0e3426bb 975 if (act == core && write_corefile (signo, detail))
28f540f4
RM
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 {
421f82e5 985 struct sigcontext *scp, ocontext;
28f540f4
RM
986 int wait_for_reply, state_changed;
987
653d74f1
JK
988 assert (ss->thread != MACH_PORT_NULL);
989
28f540f4
RM
990 /* Stop the thread and abort its pending RPC operations. */
991 if (! ss_suspended)
b96bdcd7
RM
992 {
993 err = __thread_suspend (ss->thread);
994 assert_perror (err);
995 }
28f540f4
RM
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. */
1a3a58fd 1002 abort_thread (ss, &thread_state, NULL);
28f540f4 1003
421f82e5
RM
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;
28f540f4 1010
fb8e70d6 1011 if (_hurdsig_catch_memory_fault (ss->context))
421f82e5 1012 {
421f82e5
RM
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 ();
75914335 1027
421f82e5
RM
1028 if (! machine_get_basic_state (ss->thread, &thread_state))
1029 goto sigbomb;
dc33bef3
ST
1030 loc = interrupted_reply_port_location (ss->thread,
1031 &thread_state, 1);
421f82e5
RM
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
8f0c527e 1041 assert (! __spin_lock_locked (&ss->critical_section_lock));
421f82e5
RM
1042 }
1043 else
28f540f4 1044 {
e33b438a
RM
1045 int crit = __spin_lock_locked (&ss->critical_section_lock);
1046
54da5be3 1047 wait_for_reply
e33b438a
RM
1048 = (_hurdsig_abort_rpcs (ss,
1049 /* In a critical section, any RPC
1050 should be cancelled instead of
1051 restarted, regardless of
3081378b 1052 SA_RESTART, so the entire
e33b438a
RM
1053 "atomic" operation can be aborted
1054 as a unit. */
1055 crit ? 0 : signo, 1,
54da5be3 1056 &thread_state, &state_changed,
4288c548 1057 reply)
54da5be3 1058 != MACH_PORT_NULL);
421f82e5 1059
e33b438a 1060 if (crit)
421f82e5
RM
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 ();
e33b438a
RM
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;
421f82e5
RM
1080 __thread_resume (ss->thread);
1081 break;
1082 }
28f540f4
RM
1083 }
1084
1085 /* Call the machine-dependent function to set the thread up
1086 to run the signal handler, and preserve its old context. */
e42efa01 1087 scp = _hurd_setup_sighandler (ss, action, handler, signo, detail,
28f540f4
RM
1088 wait_for_reply, &thread_state);
1089 if (scp == NULL)
421f82e5 1090 goto sigbomb;
28f540f4
RM
1091
1092 /* Set the machine-independent parts of the signal context. */
1093
28f540f4
RM
1094 {
1095 /* Fetch the thread variable for the MiG reply port,
1096 and set it to MACH_PORT_NULL. */
dc33bef3
ST
1097 mach_port_t *loc = interrupted_reply_port_location (ss->thread,
1098 &thread_state,
54da5be3 1099 1);
28f540f4
RM
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;
421f82e5
RM
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 }
28f540f4
RM
1124 }
1125
421f82e5 1126 /* Backdoor extra argument to signal handler. */
0e3426bb 1127 scp->sc_error = detail->error;
421f82e5 1128
ac61ed31 1129 /* Block requested signals while running the handler. */
28f540f4 1130 scp->sc_mask = ss->blocked;
653d74f1 1131 __sigorset (&ss->blocked, &ss->blocked, &action->sa_mask);
5d83494f 1132
ac61ed31 1133 /* Also block SIGNO unless we're asked not to. */
653d74f1 1134 if (! (action->sa_flags & (SA_RESETHAND | SA_NODEFER)))
05dea6d1 1135 __sigaddset (&ss->blocked, signo);
5d83494f 1136
ac61ed31
MK
1137 /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot
1138 be automatically reset when delivered; the system silently
1139 enforces this restriction. */
653d74f1 1140 if (action->sa_flags & SA_RESETHAND
ac61ed31 1141 && signo != SIGILL && signo != SIGTRAP)
653d74f1 1142 action->sa_handler = SIG_DFL;
28f540f4 1143
4288c548
JK
1144 /* Any sigsuspend call must return after the handler does. */
1145 wake_sigsuspend (ss);
1146
28f540f4
RM
1147 /* Start the thread running the handler (or possibly waiting for an
1148 RPC reply before running the handler). */
b96bdcd7
RM
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);
28f540f4
RM
1155 thread_state.set = 0; /* Everything we know is now wrong. */
1156 break;
1157 }
1158 }
1159
653d74f1 1160 return ss;
4288c548 1161}
28f540f4 1162
4288c548
JK
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;
7cc645ed 1174
653d74f1 1175 return _hurd_sigstate_pending (ss) & ~ss->blocked;
4288c548 1176}
75914335 1177
4288c548
JK
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;
7cc645ed 1186
653d74f1
JK
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
4288c548
JK
1191 for (signo = 1; signo < NSIG; ++signo)
1192 if (__sigismember (&pending, signo))
7cc645ed 1193 {
653d74f1
JK
1194 detail = sigstate_clear_pending (ss, signo);
1195 _hurd_sigstate_unlock (ss);
4288c548
JK
1196
1197 /* Will reacquire the lock, except if the signal is traced. */
1198 if (! post_signal (ss, signo, &detail, 0, reply))
1199 return 0;
7cc645ed 1200 }
28f540f4 1201
4288c548 1202 /* No more signals pending; SS->lock is still locked. */
653d74f1 1203 _hurd_sigstate_unlock (ss);
4288c548
JK
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 {
653d74f1 1221 _hurd_sigstate_lock (ss);
4288c548
JK
1222
1223 pending = pending_signals (ss);
1224 if (pending)
1225 /* post_pending() below will unlock SS. */
1226 break;
1227
653d74f1 1228 _hurd_sigstate_unlock (ss);
4288c548
JK
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
653d74f1
JK
1261 ss = post_signal (ss, signo, detail, untraced, reply);
1262 if (! ss)
4288c548
JK
1263 return;
1264
1265 /* The signal was neither fatal nor traced. We still hold SS->lock. */
653d74f1 1266 if (signo != 0 && ss->thread != MACH_PORT_NULL)
4288c548
JK
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_signals (ss), reply))
1274 return;
1275 }
1276 else
1277 {
653d74f1
JK
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);
4288c548
JK
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 }
28f540f4
RM
1288}
1289\f
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:
ce7f605b 1316 case SIGWINCH:
28f540f4
RM
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)))
75914335 1327 {
28f540f4
RM
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;
e0637da1 1352 int lucky = 0; /* True if we find a match for REFPORT. */
28f540f4 1353 __mutex_lock (&_hurd_dtable_lock);
e0637da1 1354 for (d = 0; !lucky && (unsigned) d < (unsigned) _hurd_dtablesize; ++d)
28f540f4
RM
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. */
e0637da1 1366 lucky = 1;
28f540f4
RM
1367 __mach_port_deallocate (__mach_task_self (), asyncid);
1368 }
1369 _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
1370 }
c90c1e1c 1371 __mutex_unlock (&_hurd_dtable_lock);
28f540f4 1372 /* If we found a lucky winner, we've set D to -1 in the loop. */
e0637da1 1373 if (lucky)
28f540f4
RM
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,
8f0c527e 1394 int signo, natural_t sigcode,
28f540f4
RM
1395 mach_port_t refport)
1396{
1397 error_t err;
93a470c7 1398 struct hurd_signal_detail d;
28f540f4
RM
1399
1400 if (err = signal_allowed (signo, refport))
1401 return err;
1402
d865ff74 1403 d.code = d.exc_subcode = sigcode;
93a470c7
RM
1404 d.exc = 0;
1405
653d74f1
JK
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,
93a470c7 1410 signo, &d, reply_port, reply_port_type,
28f540f4
RM
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,
8f0c527e 1423 int signo, natural_t sigcode,
28f540f4
RM
1424 mach_port_t refport)
1425{
1426 error_t err;
93a470c7 1427 struct hurd_signal_detail d;
28f540f4
RM
1428
1429 if (err = signal_allowed (signo, refport))
1430 return err;
1431
d865ff74 1432 d.code = d.exc_subcode = sigcode;
93a470c7
RM
1433 d.exc = 0;
1434
28f540f4
RM
1435 /* Post the signal to the designated signal-receiving thread. This will
1436 reply when the signal can be considered delivered. */
653d74f1 1437 _hurd_internal_post_signal (_hurd_global_sigstate,
93a470c7 1438 signo, &d, reply_port, reply_port_type,
28f540f4
RM
1439 1); /* Untraced flag. */
1440
1441 return MIG_NO_REPLY; /* Already replied. */
1442}
1443\f
1444extern void __mig_init (void *);
1445
1446#include <mach/task_special_ports.h>
1447
653d74f1
JK
1448/* Initialize the message port, _hurd_global_sigstate, and start the
1449 signal thread. */
28f540f4
RM
1450
1451void
62495816 1452_hurdsig_init (const int *intarray, size_t intarraysize)
28f540f4
RM
1453{
1454 error_t err;
1455 vm_size_t stacksize;
62495816 1456 struct hurd_sigstate *ss;
28f540f4
RM
1457
1458 __mutex_init (&_hurd_siglock);
1459
a5a81fec
RM
1460 err = __mach_port_allocate (__mach_task_self (),
1461 MACH_PORT_RIGHT_RECEIVE,
1462 &_hurd_msgport);
1463 assert_perror (err);
75914335 1464
28f540f4 1465 /* Make a send right to the signal port. */
a5a81fec
RM
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);
28f540f4 1471
653d74f1
JK
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(& _hurd_global_sigstate->blocked);
1478
62495816
RM
1479 /* Initialize the main thread's signal state. */
1480 ss = _hurd_self_sigstate ();
1481
653d74f1
JK
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) */
62495816
RM
1488 if (intarraysize > INIT_SIGMASK)
1489 ss->blocked = intarray[INIT_SIGMASK];
1490 if (intarraysize > INIT_SIGPENDING)
653d74f1 1491 _hurd_global_sigstate->pending = intarray[INIT_SIGPENDING];
62495816
RM
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))
653d74f1 1497 _hurd_global_sigstate->actions[signo].sa_handler = SIG_IGN;
62495816
RM
1498 }
1499
28f540f4
RM
1500 /* Start the signal thread listening on the message port. */
1501
9446e02b
ST
1502#pragma weak __pthread_create
1503 if (!__pthread_create)
72e1a750
RM
1504 {
1505 err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
1506 assert_perror (err);
28f540f4 1507
72e1a750
RM
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);
42fc12ef
ST
1514 err = __mach_setup_tls (_hurd_msgport_thread);
1515 assert_perror (err);
28f540f4 1516
72e1a750 1517 __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
28f540f4 1518
72e1a750
RM
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);
28f540f4 1522
72e1a750
RM
1523 err = __thread_resume (_hurd_msgport_thread);
1524 assert_perror (err);
1525 }
1526 else
1527 {
9446e02b
ST
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
72e1a750 1536 handlers need to take locks, so we need to be able to call into
9446e02b
ST
1537 pthread code and meet its assumptions about how our thread and
1538 its stack are arranged. Since pthread puts it there anyway,
72e1a750 1539 we'll let the signal thread's per-thread variables be found as for
9446e02b 1540 any normal pthread, and just leave the magic __hurd_sigthread_*
72e1a750 1541 values all zero so they'll be ignored. */
9446e02b
ST
1542
1543#pragma weak __pthread_detach
c2fb08c7
ST
1544#pragma weak __pthread_getattr_np
1545#pragma weak __pthread_attr_getstack
9446e02b 1546 __pthread_create(&thread, NULL, &_hurd_msgport_receive, NULL);
c2fb08c7 1547
9446e02b
ST
1548 /* Record signal thread stack layout for fork() */
1549 __pthread_getattr_np (thread, &attr);
1550 __pthread_attr_getstack (&attr, &addr, &size);
1551 __hurd_sigthread_stack_base = (uintptr_t) addr;
1552 __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + size;
1553
1554 __pthread_detach(thread);
64659255
MK
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
9446e02b 1561 pthread from here. */
64659255
MK
1562 while (_hurd_msgport_thread == 0)
1563 __swtch_pri (0);
72e1a750 1564 }
75914335 1565
28f540f4 1566 /* Receive exceptions on the signal port. */
7595ddb8 1567#ifdef TASK_EXCEPTION_PORT
28f540f4
RM
1568 __task_set_special_port (__mach_task_self (),
1569 TASK_EXCEPTION_PORT, _hurd_msgport);
7595ddb8
RM
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
159d4836
RM
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);
28f540f4
RM
1586}
1587\f /* 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,
a04549c1
JM
1598 MACH_MSG_TYPE_MAKE_SEND)
1599 || __auth_user_authenticate (new, ref,
1600 MACH_MSG_TYPE_MAKE_SEND,
1601 &ignore))
28f540f4
RM
1602 && ignore != MACH_PORT_NULL)
1603 __mach_port_deallocate (__mach_task_self (), ignore);
1604 __mach_port_destroy (__mach_task_self (), ref);
1605
762a2918 1606 /* Set the owner of the process here too. */
fb4cc8a0 1607 __mutex_lock (&_hurd_id.lock);
762a2918
UD
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));
fb4cc8a0 1614 __mutex_unlock (&_hurd_id.lock);
762a2918 1615
28f540f4
RM
1616 (void) &reauth_proc; /* Silence compiler warning. */
1617}
1618text_set_element (_hurd_reauth_hook, reauth_proc);
1619\f
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{
a753ffb2
RM
1626 if (__libc_enable_secure)
1627 return NULL;
1628
fb8e70d6 1629 if (_hurdsig_catch_memory_fault (__environ))
28f540f4
RM
1630 /* We bombed in getenv. */
1631 return NULL;
1632 else
1633 {
fb8e70d6
RM
1634 const size_t len = strlen (variable);
1635 char *value = NULL;
1636 char *volatile *ep = __environ;
1637 while (*ep)
1638 {
1639 const char *p = *ep;
10dc2a90
UD
1640 _hurdsig_fault_preemptor.first = (long int) p;
1641 _hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
fb8e70d6
RM
1642 if (! strncmp (p, variable, len) && p[len] == '=')
1643 {
fb8e70d6
RM
1644 size_t valuelen;
1645 p += len + 1;
1646 valuelen = strlen (p);
10dc2a90 1647 _hurdsig_fault_preemptor.last = (long int) (p + valuelen);
fb8e70d6
RM
1648 value = malloc (++valuelen);
1649 if (value)
1650 memcpy (value, p, valuelen);
1651 break;
1652 }
10dc2a90
UD
1653 _hurdsig_fault_preemptor.first = (long int) ++ep;
1654 _hurdsig_fault_preemptor.last = (long int) (ep + 1);
fb8e70d6 1655 }
28f540f4
RM
1656 _hurdsig_end_catch_fault ();
1657 return value;
1658 }
1659}