string: Hook up the default implementation on test-strcmp
[glibc.git] / hurd / hurdsig.c
blob56e8e6147ecdd1d4b950cb679c5c21a42120c78e
1 /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
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.
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.
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/>. */
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
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>
29 #include <hurd.h>
30 #include <hurd/id.h>
31 #include <hurd/signal.h>
33 #include "hurdfault.h"
34 #include "hurdmalloc.h" /* XXX */
35 #include "../locale/localeinfo.h"
37 #include <libc-diag.h>
39 const char *_hurdsig_getenv (const char *);
41 struct mutex _hurd_siglock;
42 int _hurd_stopped;
44 /* Port that receives signals and other miscellaneous messages. */
45 mach_port_t _hurd_msgport;
47 /* Thread listening on it. */
48 thread_t _hurd_msgport_thread;
50 /* These are set up by _hurdsig_init. */
51 unsigned long int __hurd_sigthread_stack_base;
52 unsigned long int __hurd_sigthread_stack_end;
54 /* Linked-list of per-thread signal state. */
55 struct hurd_sigstate *_hurd_sigstates;
57 /* Sigstate for the task-global signals. */
58 struct hurd_sigstate *_hurd_global_sigstate;
60 /* Timeout for RPC's after interrupt_operation. */
61 mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 60000;
63 static void
64 default_sigaction (struct sigaction actions[NSIG])
66 int signo;
68 __sigemptyset (&actions[0].sa_mask);
69 actions[0].sa_flags = SA_RESTART;
70 actions[0].sa_handler = SIG_DFL;
72 for (signo = 1; signo < NSIG; ++signo)
73 actions[signo] = actions[0];
76 struct hurd_sigstate *
77 _hurd_thread_sigstate (thread_t thread)
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)
86 ss = malloc (sizeof (*ss));
87 if (ss == NULL)
88 __libc_fatal ("hurd: Can't allocate sigstate\n");
89 __spin_lock_init (&ss->critical_section_lock);
90 __spin_lock_init (&ss->lock);
91 ss->thread = thread;
93 /* Initialize default state. */
94 __sigemptyset (&ss->blocked);
95 __sigemptyset (&ss->pending);
96 memset (&ss->sigaltstack, 0, 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;
106 if (thread == MACH_PORT_NULL)
108 /* Process-wide sigstate, use the system defaults. */
109 default_sigaction (ss->actions);
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. */
115 else
117 error_t err;
119 /* Use the global actions as a default for new threads. */
120 struct hurd_sigstate *s = _hurd_global_sigstate;
121 if (s)
123 __spin_lock (&s->lock);
124 memcpy (ss->actions, s->actions, sizeof (s->actions));
125 __spin_unlock (&s->lock);
127 else
128 default_sigaction (ss->actions);
130 ss->next = _hurd_sigstates;
131 _hurd_sigstates = ss;
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");
139 __mutex_unlock (&_hurd_siglock);
140 return ss;
142 libc_hidden_def (_hurd_thread_sigstate)
144 /* Destroy a sigstate structure. Called by libpthread just before the
145 * corresponding thread is terminated. */
146 void
147 _hurd_sigstate_delete (thread_t thread)
149 struct hurd_sigstate **ssp, *ss;
151 __mutex_lock (&_hurd_siglock);
152 for (ssp = &_hurd_sigstates; *ssp; ssp = &(*ssp)->next)
153 if ((*ssp)->thread == thread)
154 break;
156 ss = *ssp;
157 if (ss)
158 *ssp = ss->next;
160 __mutex_unlock (&_hurd_siglock);
161 if (ss)
163 if (ss->thread != MACH_PORT_NULL)
164 __mach_port_deallocate (__mach_task_self (), ss->thread);
166 free (ss);
170 /* Make SS a global receiver, with pthread signal semantics. */
171 void
172 _hurd_sigstate_set_global_rcv (struct hurd_sigstate *ss)
174 assert (ss->thread != MACH_PORT_NULL);
175 ss->actions[0].sa_handler = SIG_IGN;
178 /* Check whether SS is a global receiver. */
179 static int
180 sigstate_is_global_rcv (const struct hurd_sigstate *ss)
182 return (_hurd_global_sigstate != NULL)
183 && (ss->actions[0].sa_handler == SIG_IGN);
185 libc_hidden_def (_hurd_sigstate_delete)
187 /* Lock/unlock a hurd_sigstate structure. If the accessors below require
188 it, the global sigstate will be locked as well. */
189 void
190 _hurd_sigstate_lock (struct hurd_sigstate *ss)
192 if (sigstate_is_global_rcv (ss))
193 __spin_lock (&_hurd_global_sigstate->lock);
194 __spin_lock (&ss->lock);
196 void
197 _hurd_sigstate_unlock (struct hurd_sigstate *ss)
199 __spin_unlock (&ss->lock);
200 if (sigstate_is_global_rcv (ss))
201 __spin_unlock (&_hurd_global_sigstate->lock);
203 libc_hidden_def (_hurd_sigstate_set_global_rcv)
205 /* Retreive a thread's full set of pending signals, including the global
206 ones if appropriate. SS must be locked. */
207 sigset_t
208 _hurd_sigstate_pending (const struct hurd_sigstate *ss)
210 sigset_t pending = ss->pending;
211 if (sigstate_is_global_rcv (ss))
212 __sigorset (&pending, &pending, &_hurd_global_sigstate->pending);
213 return pending;
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. */
219 static struct hurd_signal_detail
220 sigstate_clear_pending (struct hurd_sigstate *ss, int signo)
222 if (sigstate_is_global_rcv (ss)
223 && __sigismember (&_hurd_global_sigstate->pending, signo))
225 __sigdelset (&_hurd_global_sigstate->pending, signo);
226 return _hurd_global_sigstate->pending_data[signo];
229 assert (__sigismember (&ss->pending, signo));
230 __sigdelset (&ss->pending, signo);
231 return ss->pending_data[signo];
233 libc_hidden_def (_hurd_sigstate_lock)
234 libc_hidden_def (_hurd_sigstate_unlock)
236 /* Retreive a thread's action vector. SS must be locked. */
237 struct sigaction *
238 _hurd_sigstate_actions (struct hurd_sigstate *ss)
240 if (sigstate_is_global_rcv (ss))
241 return _hurd_global_sigstate->actions;
242 else
243 return ss->actions;
245 libc_hidden_def (_hurd_sigstate_pending)
248 /* Signal delivery itself is on this page. */
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>
265 /* Call the crash dump server to mummify us before we die.
266 Returns nonzero if a core file was written. */
267 static int
268 write_corefile (int signo, const struct hurd_signal_detail *detail)
270 error_t err;
271 mach_port_t coreserver;
272 file_t file, coredir;
273 const char *name;
275 /* Don't bother locking since we just read the one word. */
276 rlim_t corelimit = _hurd_rlimits[RLIMIT_CORE].rlim_cur;
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;
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. */
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;
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);
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);
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;
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
336 /* SS->thread is suspended. Abort the thread and get its basic state. */
337 static void
338 abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
339 void (*reply) (void))
341 assert (ss->thread != MACH_PORT_NULL);
343 if (!(state->set & THREAD_ABORTED))
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;
352 if (reply)
353 (*reply) ();
355 machine_get_basic_state (ss->thread, state);
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. */
362 static mach_port_t *
363 interrupted_reply_port_location (thread_t thread,
364 struct machine_thread_all_state *thread_state,
365 int sigthread)
367 mach_port_t *portloc = &THREAD_TCB(thread, thread_state)->reply_port;
369 if (sigthread && _hurdsig_catch_memory_fault (portloc))
370 /* Faulted trying to read the TCB. */
371 return NULL;
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;
382 if (sigthread)
383 _hurdsig_end_catch_fault ();
385 return portloc;
388 #include <hurd/sigpreempt.h>
389 #include <intr-msg.h>
391 /* Timeout on interrupt_operation calls. */
392 mach_msg_timeout_t _hurdsig_interrupt_timeout = 1000;
394 /* SS->thread is suspended.
396 Abort any interruptible RPC operation the thread is doing.
398 This uses only the constant member SS->thread and the unlocked, atomically
399 set member SS->intr_port, so no locking is needed.
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.
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).
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. */
412 mach_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))
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;
422 *state_change = 0;
424 intr_port = ss->intr_port;
425 if (intr_port == MACH_PORT_NULL)
426 /* No interruption needs done. */
427 return MACH_PORT_NULL;
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);
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)
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;
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)
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. */
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);
465 if (err)
467 if (reply)
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;
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;
484 else if (reply)
485 rcv_port = *reply;
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;
495 return rcv_port;
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. */
505 static void
506 abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
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. */
512 struct hurd_sigstate *ss;
513 size_t nthreads;
514 mach_port_t *reply_ports;
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;
522 reply_ports = alloca (nthreads * sizeof *reply_ports);
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
530 int state_changed;
531 state->set = 0; /* Reset scratch area. */
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)
541 if (reply_ports[nthreads] != MACH_PORT_NULL)
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;
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);
558 /* Wait for replies from all the successfully interrupted RPCs. */
559 while (nthreads-- > 0)
560 if (reply_ports[nthreads] != MACH_PORT_NULL)
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)
569 case MACH_RCV_TIMED_OUT:
570 case MACH_RCV_TOO_LARGE:
571 break;
573 default:
574 assert_perror (err);
579 /* Wake up any sigsuspend or pselect call that is blocking SS->thread. SS must
580 be locked. */
581 static void
582 wake_sigsuspend (struct hurd_sigstate *ss)
584 error_t err;
585 mach_msg_header_t msg;
587 if (ss->suspended == MACH_PORT_NULL)
588 return;
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);
603 struct hurd_signal_preemptor *_hurdsig_preemptors = 0;
604 sigset_t _hurdsig_preempted_set;
606 /* XXX temporary to deal with spelling fix */
607 weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
609 /* Mask of stop signals. */
610 #define STOPSIGS (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) \
611 | __sigmask (SIGSTOP) | __sigmask (SIGTSTP))
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. */
618 static struct hurd_sigstate *
619 post_signal (struct hurd_sigstate *ss,
620 int signo, struct hurd_signal_detail *detail,
621 int untraced, void (*reply) (void))
623 struct machine_thread_all_state thread_state;
624 enum { stop, ignore, core, term, handle } act;
625 int ss_suspended;
627 /* sigaction for preemptors */
628 struct sigaction preempt_sigaction = {
629 .sa_flags = SA_RESTART
632 struct sigaction *action;
634 /* Mark the signal as pending. */
635 void mark_pending (void)
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;
643 /* Suspend the process with SIGNO. */
644 void suspend (void)
646 /* Stop all other threads and mark ourselves stopped. */
647 __USEPORT (PROC,
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;
660 /* Resume the process after a suspension. */
661 void resume (void)
663 /* Resume the process from being stopped. */
664 thread_t *threads;
665 mach_msg_type_number_t nthreads, i;
666 error_t err;
668 if (! _hurd_stopped)
669 return;
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)
678 if (act == handle && threads[i] == ss->thread)
680 /* The thread that will run the handler is kept suspended. */
681 ss_suspended = 1;
683 else if (threads[i] != _hurd_msgport_thread)
685 err = __thread_resume (threads[i]);
686 assert_perror (err);
688 err = __mach_port_deallocate (__mach_task_self (),
689 threads[i]);
690 assert_perror (err);
692 __vm_deallocate (__mach_task_self (),
693 (vm_address_t) threads,
694 nthreads * sizeof *threads);
695 _hurd_stopped = 0;
698 error_t err;
699 sighandler_t handler;
701 if (signo == 0)
703 if (untraced)
705 /* This is PTRACE_CONTINUE. */
706 act = ignore;
707 resume ();
710 /* This call is just to check for pending signals. */
711 _hurd_sigstate_lock (ss);
712 return ss;
715 thread_state.set = 0; /* We know nothing. */
717 _hurd_sigstate_lock (ss);
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)
724 struct hurd_sigstate *rss;
726 __mutex_lock (&_hurd_siglock);
727 for (rss = _hurd_sigstates; rss != NULL; rss = rss->next)
729 if (! sigstate_is_global_rcv (rss))
730 continue;
732 /* The global sigstate is already locked. */
733 __spin_lock (&rss->lock);
734 if (! __sigismember (&rss->blocked, signo))
736 ss = rss;
737 break;
739 __spin_unlock (&rss->lock);
741 __mutex_unlock (&_hurd_siglock);
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;
749 /* Check for a preempted signal. Preempted signals can arrive during
750 critical sections. */
752 inline sighandler_t try_preemptor (struct hurd_signal_preemptor *pe)
753 { /* PE cannot be null. */
756 if (HURD_PREEMPT_SIGNAL_P (pe, signo, detail->exc_subcode))
758 if (pe->preemptor)
760 sighandler_t handler = (*pe->preemptor) (pe, ss,
761 &signo, detail);
762 if (handler != SIG_ERR)
763 return handler;
765 else
766 return pe->handler;
768 pe = pe->next;
769 } while (pe != 0);
770 return SIG_ERR;
773 handler = ss->preemptors ? try_preemptor (ss->preemptors) : SIG_ERR;
775 /* If no thread-specific preemptor, check for a global one. */
776 if (handler == SIG_ERR && __sigismember (&_hurdsig_preempted_set, signo))
778 __mutex_lock (&_hurd_siglock);
779 handler = try_preemptor (_hurdsig_preemptors);
780 __mutex_unlock (&_hurd_siglock);
784 ss_suspended = 0;
786 if (handler == SIG_IGN)
787 /* Ignore the signal altogether. */
788 act = ignore;
789 else if (handler != SIG_ERR)
791 /* Run the preemption-provided handler. */
792 action = &preempt_sigaction;
793 act = handle;
795 else
797 /* No preemption. Do normal handling. */
799 action = & _hurd_sigstate_actions (ss) [signo];
801 if (!untraced && __sigismember (&_hurdsig_traced, signo))
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;
815 handler = action->sa_handler;
817 if (handler == SIG_DFL)
818 /* Figure out the default action for this signal. */
819 switch (signo)
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;
827 case SIGTTIN:
828 case SIGTTOU:
829 case SIGSTOP:
830 case SIGTSTP:
831 act = stop;
832 break;
834 case SIGCONT:
835 case SIGIO:
836 case SIGURG:
837 case SIGCHLD:
838 case SIGWINCH:
839 act = ignore;
840 break;
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;
854 case SIGINFO:
855 if (_hurd_pgrp == _hurd_pid)
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;
866 else
867 act = ignore;
868 break;
870 default:
871 act = term;
872 break;
874 else if (handler == SIG_IGN)
875 act = ignore;
876 else
877 act = handle;
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 (&ss->pending, SIGCONT);
883 else
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;
890 if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
891 resume ();
895 if (_hurd_orphaned && act == stop
896 && (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU)
897 | __sigmask (SIGTSTP))))
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;
907 /* Handle receipt of a blocked signal, or any signal while stopped. */
908 if (__sigismember (&blocked, signo) || (signo != SIGKILL && _hurd_stopped))
910 mark_pending ();
911 act = ignore;
914 /* Perform the chosen action for the signal. */
915 switch (act)
917 case stop:
918 if (_hurd_stopped)
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);
927 else
928 /* Suspend the process. */
929 suspend ();
930 break;
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;
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)
943 assert (ss->thread != MACH_PORT_NULL);
944 err = __thread_resume (ss->thread);
945 assert_perror (err);
946 ss_suspended = 0;
948 break;
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;
956 fatal:
957 act = core;
958 /* FALLTHROUGH */
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, &thread_state, 0);
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 */
982 case handle:
983 /* Call a handler for this signal. */
985 struct sigcontext *scp, ocontext;
986 int wait_for_reply, state_changed;
988 assert (ss->thread != MACH_PORT_NULL);
990 /* Stop the thread and abort its pending RPC operations. */
991 if (! ss_suspended)
993 err = __thread_suspend (ss->thread);
994 assert_perror (err);
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, &thread_state, NULL);
1004 if (ss->context)
1006 /* We have a previous sigcontext that sigreturn was about
1007 to restore when another signal arrived. */
1009 mach_port_t *loc;
1011 if (_hurdsig_catch_memory_fault (ss->context))
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;
1019 else
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;
1026 _hurdsig_end_catch_fault ();
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);
1038 /* The thread was in sigreturn, not in any interruptible RPC. */
1039 wait_for_reply = 0;
1041 assert (! __spin_lock_locked (&ss->critical_section_lock));
1043 else
1045 int crit = __spin_lock_locked (&ss->critical_section_lock);
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);
1060 if (crit)
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;
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 wait_for_reply, &thread_state);
1089 if (scp == NULL)
1090 goto sigbomb;
1092 /* Set the machine-independent parts of the signal context. */
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,
1100 if (loc)
1102 scp->sc_reply_port = *loc;
1103 *loc = MACH_PORT_NULL;
1105 else
1106 scp->sc_reply_port = MACH_PORT_NULL;
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;
1113 if (ss->context)
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. */
1119 scp->sc_reply_port = ss->context->sc_reply_port;
1120 scp->sc_intr_port = ss->context->sc_intr_port;
1122 ss->context = NULL;
1126 /* Backdoor extra argument to signal handler. */
1127 scp->sc_error = detail->error;
1129 /* Block requested signals while running the handler. */
1130 scp->sc_mask = ss->blocked;
1131 __sigorset (&ss->blocked, &ss->blocked, &action->sa_mask);
1133 /* Also block SIGNO unless we're asked not to. */
1134 if (! (action->sa_flags & (SA_RESETHAND | SA_NODEFER)))
1135 __sigaddset (&ss->blocked, signo);
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;
1144 /* Any sigsuspend call must return after the handler does. */
1145 wake_sigsuspend (ss);
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;
1160 return ss;
1163 /* Return the set of pending signals in SS which should be delivered. */
1164 static sigset_t
1165 pending_signals (struct hurd_sigstate *ss)
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;
1175 return _hurd_sigstate_pending (ss) & ~ss->blocked;
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. */
1181 static int
1182 post_pending (struct hurd_sigstate *ss, sigset_t pending, void (*reply) (void))
1184 int signo;
1185 struct hurd_signal_detail detail;
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);
1191 for (signo = 1; signo < NSIG; ++signo)
1192 if (__sigismember (&pending, signo))
1194 detail = sigstate_clear_pending (ss, signo);
1195 _hurd_sigstate_unlock (ss);
1197 /* Will reacquire the lock, except if the signal is traced. */
1198 if (! post_signal (ss, signo, &detail, 0, reply))
1199 return 0;
1202 /* No more signals pending; SS->lock is still locked. */
1203 _hurd_sigstate_unlock (ss);
1205 return 1;
1208 /* Post all the pending signals of all threads and return 1. If a traced
1209 signal is encountered, abort immediately and return 0. */
1210 static int
1211 post_all_pending_signals (void (*reply) (void))
1213 struct hurd_sigstate *ss;
1214 sigset_t pending = 0;
1216 for (;;)
1218 __mutex_lock (&_hurd_siglock);
1219 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
1221 _hurd_sigstate_lock (ss);
1223 pending = pending_signals (ss);
1224 if (pending)
1225 /* post_pending() below will unlock SS. */
1226 break;
1228 _hurd_sigstate_unlock (ss);
1230 __mutex_unlock (&_hurd_siglock);
1232 if (! pending)
1233 return 1;
1234 if (! post_pending (ss, pending, reply))
1235 return 0;
1239 /* Deliver a signal. SS is not locked. */
1240 void
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)
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)
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);
1261 ss = post_signal (ss, signo, detail, untraced, reply);
1262 if (! ss)
1263 return;
1265 /* The signal was neither fatal nor traced. We still hold SS->lock. */
1266 if (signo != 0 && ss->thread != MACH_PORT_NULL)
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 ();
1272 /* Post any pending signals for this thread. */
1273 if (! post_pending (ss, pending_signals (ss), reply))
1274 return;
1276 else
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;
1284 /* All pending signals delivered to all threads.
1285 Now we can send the reply message even for signal 0. */
1286 reply ();
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. */
1293 static error_t
1294 signal_allowed (int signo, mach_port_t refport)
1296 if (signo < 0 || signo >= NSIG)
1297 return EINVAL;
1299 if (refport == __mach_task_self ())
1300 /* Can send any signal. */
1301 goto win;
1303 /* Avoid needing to check for this below. */
1304 if (refport == MACH_PORT_NULL)
1305 return EPERM;
1307 switch (signo)
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;
1322 case SIGCONT:
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)))
1328 __mach_port_deallocate (__mach_task_self (), sessport);
1329 if (refport == sessport)
1330 goto win;
1333 break;
1335 case SIGIO:
1336 case SIGURG:
1338 /* Any io object a file descriptor refers to might send us
1339 one of these signals using its async ID port for REFPORT.
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.
1348 Someday we could implement some reasonable scheme for
1349 authorizing SIGIO and SIGURG signals properly. */
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)
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))
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);
1369 _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
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;
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;
1382 win:
1383 /* Deallocate the REFPORT send right; we are done with it. */
1384 __mach_port_deallocate (__mach_task_self (), refport);
1386 return 0;
1389 /* Implement the sig_post RPC from <hurd/msg.defs>;
1390 sent when someone wants us to get a signal. */
1391 kern_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)
1397 error_t err;
1398 struct hurd_signal_detail d;
1400 if (err = signal_allowed (signo, refport))
1401 return err;
1403 d.code = d.exc_subcode = sigcode;
1404 d.exc = 0;
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. */
1413 return MIG_NO_REPLY; /* Already replied. */
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. */
1419 kern_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)
1426 error_t err;
1427 struct hurd_signal_detail d;
1429 if (err = signal_allowed (signo, refport))
1430 return err;
1432 d.code = d.exc_subcode = sigcode;
1433 d.exc = 0;
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. */
1441 return MIG_NO_REPLY; /* Already replied. */
1444 extern void __mig_init (void *);
1446 #include <mach/task_special_ports.h>
1448 /* Initialize the message port, _hurd_global_sigstate, and start the
1449 signal thread. */
1451 void
1452 _hurdsig_init (const int *intarray, size_t intarraysize)
1454 error_t err;
1455 vm_size_t stacksize;
1456 struct hurd_sigstate *ss;
1458 __mutex_init (&_hurd_siglock);
1460 err = __mach_port_allocate (__mach_task_self (),
1461 MACH_PORT_RIGHT_RECEIVE,
1462 &_hurd_msgport);
1463 assert_perror (err);
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);
1472 /* Initialize the global signal state. */
1473 _hurd_global_sigstate = _hurd_thread_sigstate (MACH_PORT_NULL);
1475 /* We block all signals, and let actual threads pull them from the
1476 pending mask. */
1477 __sigfillset(& _hurd_global_sigstate->blocked);
1479 /* Initialize the main thread's signal state. */
1480 ss = _hurd_self_sigstate ();
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);
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)
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;
1500 /* Start the signal thread listening on the message port. */
1502 #pragma weak __pthread_create
1503 if (!__pthread_create)
1505 err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
1506 assert_perror (err);
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);
1517 __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
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);
1523 err = __thread_resume (_hurd_msgport_thread);
1524 assert_perror (err);
1526 else
1528 pthread_t thread;
1529 pthread_attr_t attr;
1530 void *addr;
1531 size_t size;
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. */
1543 #pragma weak __pthread_detach
1544 #pragma weak __pthread_getattr_np
1545 #pragma weak __pthread_attr_getstack
1546 __pthread_create(&thread, NULL, &_hurd_msgport_receive, NULL);
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;
1554 __pthread_detach(thread);
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);
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
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);
1587 \f /* XXXX */
1588 /* Reauthenticate with the proc server. */
1590 static void
1591 reauth_proc (mach_port_t new)
1593 mach_port_t ref, ignore;
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);
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);
1616 (void) &reauth_proc; /* Silence compiler warning. */
1618 text_set_element (_hurd_reauth_hook, reauth_proc);
1620 /* Like `getenv', but safe for the signal thread to run.
1621 If the environment is trashed, this will just return NULL. */
1623 const char *
1624 _hurdsig_getenv (const char *variable)
1626 if (__libc_enable_secure)
1627 return NULL;
1629 if (_hurdsig_catch_memory_fault (__environ))
1630 /* We bombed in getenv. */
1631 return NULL;
1632 else
1634 const size_t len = strlen (variable);
1635 char *value = NULL;
1636 char *volatile *ep = __environ;
1637 while (*ep)
1639 const char *p = *ep;
1640 _hurdsig_fault_preemptor.first = (long int) p;
1641 _hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
1642 if (! strncmp (p, variable, len) && p[len] == '=')
1644 size_t valuelen;
1645 p += len + 1;
1646 valuelen = strlen (p);
1647 _hurdsig_fault_preemptor.last = (long int) (p + valuelen);
1648 value = malloc (++valuelen);
1649 if (value)
1650 memcpy (value, p, valuelen);
1651 break;
1653 _hurdsig_fault_preemptor.first = (long int) ++ep;
1654 _hurdsig_fault_preemptor.last = (long int) (ep + 1);
1656 _hurdsig_end_catch_fault ();
1657 return value;