initial import
[glibc.git] / hurd / hurdsig.c
blob2c6f6a17d2973b758c7a537ed5563b39cf1da4d4
1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 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 Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 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 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <hurd.h>
22 #include <hurd/signal.h>
23 #include <cthreads.h> /* For `struct mutex'. */
24 #include <string.h>
25 #include "hurdfault.h"
26 #include "hurdmalloc.h" /* XXX */
28 const char *_hurdsig_getenv (const char *);
30 struct mutex _hurd_siglock;
31 int _hurd_stopped;
33 /* Port that receives signals and other miscellaneous messages. */
34 mach_port_t _hurd_msgport;
36 /* Thread listening on it. */
37 thread_t _hurd_msgport_thread;
39 /* Thread which receives task-global signals. */
40 thread_t _hurd_sigthread;
42 /* Linked-list of per-thread signal state. */
43 struct hurd_sigstate *_hurd_sigstates;
45 static void
46 default_sigaction (struct sigaction actions[NSIG])
48 int signo;
50 __sigemptyset (&actions[0].sa_mask);
51 actions[0].sa_flags = SA_RESTART;
52 actions[0].sa_handler = SIG_DFL;
54 for (signo = 1; signo < NSIG; ++signo)
55 actions[signo] = actions[0];
58 struct hurd_sigstate *
59 _hurd_thread_sigstate (thread_t thread)
61 struct hurd_sigstate *ss;
62 __mutex_lock (&_hurd_siglock);
63 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
64 if (ss->thread == thread)
65 break;
66 if (ss == NULL)
68 ss = malloc (sizeof (*ss));
69 if (ss == NULL)
70 __libc_fatal ("hurd: Can't allocate thread sigstate\n");
71 ss->thread = thread;
72 __spin_lock_init (&ss->lock);
74 /* Initialze default state. */
75 __sigemptyset (&ss->blocked);
76 __sigemptyset (&ss->pending);
77 memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
78 ss->suspended = 0;
79 #ifdef noteven
80 __condition_init (&ss->arrived);
81 #endif
82 ss->intr_port = MACH_PORT_NULL;
83 ss->context = NULL;
85 /* Initialize the sigaction vector from the default signal receiving
86 thread's state, and its from the system defaults. */
87 if (thread == _hurd_sigthread)
88 default_sigaction (ss->actions);
89 else
91 struct hurd_sigstate *s;
92 for (s = _hurd_sigstates; s != NULL; s = s->next)
93 if (s->thread == _hurd_sigthread)
94 break;
95 if (s)
97 __spin_lock (&s->lock);
98 memcpy (ss->actions, s->actions, sizeof (s->actions));
99 __spin_unlock (&s->lock);
101 else
102 default_sigaction (ss->actions);
105 ss->next = _hurd_sigstates;
106 _hurd_sigstates = ss;
108 __mutex_unlock (&_hurd_siglock);
109 return ss;
112 /* Signal delivery itself is on this page. */
114 #include <hurd/fd.h>
115 #include <hurd/core.h>
116 #include <hurd/paths.h>
117 #include <setjmp.h>
118 #include <fcntl.h>
119 #include <sys/wait.h>
120 #include "thread_state.h"
121 #include <hurd/msg_server.h>
122 #include <hurd/msg_reply.h> /* For __msg_sig_post_reply. */
123 #include <assert.h>
124 #include <hurd/interrupt.h>
126 int _hurd_core_limit; /* XXX */
128 /* Call the core server to mummify us before we die.
129 Returns nonzero if a core file was written. */
130 static int
131 write_corefile (int signo, long int sigcode, int sigerror)
133 error_t err;
134 mach_port_t coreserver;
135 file_t file, coredir;
136 const char *name;
138 /* XXX RLIMIT_CORE:
139 When we have a protocol to make the server return an error
140 for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE
141 value in place of the RLIMIT_FSIZE value. */
143 /* First get a port to the core dumping server. */
144 coreserver = MACH_PORT_NULL;
145 name = _hurdsig_getenv ("CORESERVER");
146 if (name != NULL)
147 coreserver = __file_name_lookup (name, 0, 0);
148 if (coreserver == MACH_PORT_NULL)
149 coreserver = __file_name_lookup (_SERVERS_CORE, 0, 0);
150 if (coreserver == MACH_PORT_NULL)
151 return 0;
153 /* Get a port to the directory where the new core file will reside. */
154 name = _hurdsig_getenv ("COREFILE");
155 if (name == NULL)
156 name = "core";
157 coredir = __file_name_split (name, (char **) &name);
158 if (coredir == MACH_PORT_NULL)
159 return 0;
160 /* Create the new file, but don't link it into the directory yet. */
161 if (err = __dir_mkfile (coredir, O_WRONLY|O_CREAT,
162 0600 & ~_hurd_umask, /* XXX ? */
163 &file))
164 return 0;
166 /* Call the core dumping server to write the core file. */
167 err = __core_dump_task (coreserver,
168 __mach_task_self (),
169 file, _hurdsig_getenv ("GNUTARGET"),
170 signo, sigcode, sigerror);
171 __mach_port_deallocate (__mach_task_self (), coreserver);
172 if (! err)
173 /* The core dump into FILE succeeded, so now link it into the
174 directory. */
175 err = __dir_link (file, coredir, name);
176 __mach_port_deallocate (__mach_task_self (), file);
177 __mach_port_deallocate (__mach_task_self (), coredir);
178 return !err;
182 /* Send a sig_post reply message if it hasn't already been sent. */
183 static inline void
184 post_reply (mach_port_t *reply_port, mach_msg_type_name_t reply_port_type,
185 int untraced,
186 error_t result)
188 if (reply_port == NULL || *reply_port == MACH_PORT_NULL)
189 return;
190 (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply)
191 (*reply_port, reply_port_type, result);
192 *reply_port = MACH_PORT_NULL;
196 /* The lowest-numbered thread state flavor value is 1,
197 so we use bit 0 in machine_thread_all_state.set to
198 record whether we have done thread_abort. */
199 #define THREAD_ABORTED 1
201 /* SS->thread is suspended. Abort the thread and get its basic state. If
202 REPLY_PORT is not NULL, send a reply on *REPLY_PORT after aborting the
203 thread. */
204 static void
205 abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
206 mach_port_t *reply_port, mach_msg_type_name_t reply_port_type,
207 int untraced)
209 if (!(state->set & THREAD_ABORTED))
211 __thread_abort (ss->thread);
212 /* Clear all thread state flavor set bits, because thread_abort may
213 have changed the state. */
214 state->set = THREAD_ABORTED;
217 if (reply_port)
218 post_reply (reply_port, reply_port_type, untraced, 0);
220 machine_get_basic_state (ss->thread, state);
223 /* Find the location of the MiG reply port cell in use by the thread whose
224 state is described by THREAD_STATE. Make sure that this location can be
225 set without faulting, or else return NULL. */
227 static mach_port_t *
228 interrupted_reply_port_location (struct machine_thread_all_state *thread_state)
230 mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
231 (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
233 if (_hurdsig_catch_fault (SIGSEGV))
235 assert (_hurdsig_fault_sigcode == (long int) portloc);
236 /* Faulted trying to read the stack. */
237 return NULL;
240 /* Fault now if this pointer is bogus. */
241 *(volatile mach_port_t *) portloc = *portloc;
243 _hurdsig_end_catch_fault ();
245 return portloc;
249 /* SS->thread is suspended.
251 Abort any interruptible RPC operation the thread is doing.
253 This uses only the constant member SS->thread and the unlocked, atomically
254 set member SS->intr_port, so no locking is needed.
256 If successfully sent an interrupt_operation and therefore the thread should
257 wait for its pending RPC to return (possibly EINTR) before taking the
258 incoming signal, returns the reply port to be received on. Otherwise
259 returns MACH_PORT_NULL.
261 *STATE_CHANGE is set nonzero if STATE->basic was modified and should
262 be applied back to the thread if it might ever run again, else zero. */
264 static mach_port_t
265 abort_rpcs (struct hurd_sigstate *ss, int signo,
266 struct machine_thread_all_state *state, int *state_change,
267 mach_port_t *reply_port, mach_msg_type_name_t reply_port_type,
268 int untraced)
270 mach_port_t msging_port;
271 mach_port_t intr_port;
273 *state_change = 0;
275 intr_port = ss->intr_port;
276 if (intr_port == MACH_PORT_NULL)
277 /* No interruption needs done. */
278 return MACH_PORT_NULL;
280 /* Abort the thread's kernel context, so any pending message send or
281 receive completes immediately or aborts. */
282 abort_thread (ss, state, reply_port, reply_port_type, untraced);
284 if (_hurdsig_rcv_interrupted_p (state, &msging_port))
286 error_t err;
288 /* The RPC request message was sent and the thread was waiting for
289 the reply message; now the message receive has been aborted, so
290 the mach_msg_call will return MACH_RCV_INTERRUPTED. We must tell
291 the server to interrupt the pending operation. The thread must
292 wait for the reply message before running the signal handler (to
293 guarantee that the operation has finished being interrupted), so
294 our nonzero return tells the trampoline code to finish the message
295 receive operation before running the handler. */
297 err = __interrupt_operation (intr_port);
299 if (err)
301 mach_port_t *reply;
303 /* The interrupt didn't work.
304 Destroy the receive right the thread is blocked on. */
305 __mach_port_destroy (__mach_task_self (), msging_port);
307 /* The system call return value register now contains
308 MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
309 call. Since we have just destroyed the receive right, the
310 retry will fail with MACH_RCV_INVALID_NAME. Instead, just
311 change the return value here to EINTR so mach_msg will not
312 retry and the EINTR error code will propagate up. */
313 state->basic.SYSRETURN = EINTR;
314 *state_change = 1;
316 /* If that was the thread's MiG reply port (which I think should
317 always be the case), clear the reply port cell so it won't be
318 reused. */
319 reply = interrupted_reply_port_location (state);
320 if (reply != NULL && *reply == msging_port)
321 *reply = MACH_PORT_NULL;
324 /* All threads whose RPCs were interrupted by the interrupt_operation
325 call above will retry their RPCs unless we clear SS->intr_port.
326 So we clear it for the thread taking a signal when SA_RESTART is
327 clear, so that its call returns EINTR. */
328 if (!(ss->actions[signo].sa_flags & SA_RESTART))
329 ss->intr_port = MACH_PORT_NULL;
331 return err ? MACH_PORT_NULL : msging_port;
334 /* One of the following is true:
336 1. The RPC has not yet been sent. The thread will start its operation
337 after the signal has been handled.
339 2. The RPC has finished, but not yet cleared SS->intr_port.
340 The thread will clear SS->intr_port after running the handler.
342 3. The RPC request message was being sent was aborted. The mach_msg
343 system call will return MACH_SEND_INTERRUPTED, and HURD_EINTR_RPC will
344 notice the interruption (either retrying the RPC or returning EINTR). */
346 return MACH_PORT_NULL;
349 /* Abort the RPCs being run by all threads but this one;
350 all other threads should be suspended. If LIVE is nonzero, those
351 threads may run again, so they should be adjusted as necessary to be
352 happy when resumed. STATE is clobbered as a scratch area; its initial
353 contents are ignored, and its contents on return are not useful. */
355 static void
356 abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
358 /* We can just loop over the sigstates. Any thread doing something
359 interruptible must have one. We needn't bother locking because all
360 other threads are stopped. */
362 struct hurd_sigstate *ss;
363 size_t nthreads;
364 mach_port_t *reply_ports;
366 /* First loop over the sigstates to count them.
367 We need to know how big a vector we will need for REPLY_PORTS. */
368 nthreads = 0;
369 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
370 ++nthreads;
372 reply_ports = alloca (nthreads * sizeof *reply_ports);
374 nthreads = 0;
375 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
376 if (ss->thread == _hurd_msgport_thread)
377 reply_ports[nthreads++] = MACH_PORT_NULL;
378 else
380 int state_changed;
381 state->set = 0; /* Reset scratch area. */
383 /* Abort any operation in progress with interrupt_operation.
384 Record the reply port the thread is waiting on.
385 We will wait for all the replies below. */
386 reply_ports[nthreads++] = abort_rpcs (ss, signo, state, &state_changed,
387 NULL, 0, 0);
388 if (state_changed && live)
389 /* Aborting the RPC needed to change this thread's state,
390 and it might ever run again. So write back its state. */
391 __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
392 (natural_t *) &state->basic,
393 MACHINE_THREAD_STATE_COUNT);
396 /* Wait for replies from all the successfully interrupted RPCs. */
397 while (nthreads-- > 0)
398 if (reply_ports[nthreads] != MACH_PORT_NULL)
400 error_t err;
401 mach_msg_header_t head;
402 err = __mach_msg (&head, MACH_RCV_MSG, 0, sizeof head,
403 reply_ports[nthreads],
404 MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
405 if (err != MACH_RCV_TOO_LARGE)
406 assert_perror (err);
411 struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
412 struct mutex _hurd_signal_preempt_lock;
414 /* Mask of stop signals. */
415 #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
416 sigmask (SIGSTOP) | sigmask (SIGTSTP))
418 /* Deliver a signal. SS is not locked. */
419 void
420 _hurd_internal_post_signal (struct hurd_sigstate *ss,
421 int signo, long int sigcode, int sigerror,
422 mach_port_t reply_port,
423 mach_msg_type_name_t reply_port_type,
424 int untraced)
426 struct machine_thread_all_state thread_state;
427 enum { stop, ignore, core, term, handle } act;
428 sighandler_t handler;
429 struct hurd_signal_preempt *pe;
430 sighandler_t (*preempt) (thread_t, int, long int, int) = NULL;
431 sigset_t pending;
432 int ss_suspended;
434 /* Reply to this sig_post message. */
435 inline void reply (void)
437 post_reply (&reply_port, reply_port_type, untraced, 0);
440 /* Mark the signal as pending. */
441 void mark_pending (void)
443 __sigaddset (&ss->pending, signo);
444 /* Save the code to be given to the handler when SIGNO is
445 unblocked. */
446 ss->pending_data[signo].code = sigcode;
447 ss->pending_data[signo].error = sigerror;
450 /* Suspend the process with SIGNO. */
451 void suspend (void)
453 /* Stop all other threads and mark ourselves stopped. */
454 __USEPORT (PROC,
456 /* Hold the siglock while stopping other threads to be
457 sure it is not held by another thread afterwards. */
458 __mutex_lock (&_hurd_siglock);
459 __proc_dostop (port, _hurd_msgport_thread);
460 __mutex_unlock (&_hurd_siglock);
461 abort_all_rpcs (signo, &thread_state, 1);
462 __proc_mark_stop (port, signo);
463 }));
464 _hurd_stopped = 1;
467 post_signal:
469 thread_state.set = 0; /* We know nothing. */
471 /* Check for a preempted signal. Preempted signals
472 can arrive during critical sections. */
473 __mutex_lock (&_hurd_signal_preempt_lock);
474 for (pe = _hurd_signal_preempt[signo]; pe != NULL; pe = pe->next)
475 if (sigcode >= pe->first && sigcode <= pe->last)
477 preempt = pe->handler;
478 break;
480 __mutex_unlock (&_hurd_signal_preempt_lock);
482 handler = SIG_DFL;
483 if (preempt)
484 /* Let the preempting handler examine the thread.
485 If it returns SIG_DFL, we run the normal handler;
486 otherwise we use the handler it returns. */
487 handler = (*preempt) (ss->thread, signo, sigcode, sigerror);
489 ss_suspended = 0;
491 if (handler != SIG_DFL)
492 /* Run the preemption-provided handler. */
493 act = handle;
494 else
496 /* No preemption. Do normal handling. */
498 __spin_lock (&ss->lock);
500 handler = ss->actions[signo].sa_handler;
502 if (!untraced && (_hurd_exec_flags & EXEC_TRACED))
504 /* We are being traced. Stop to tell the debugger of the signal. */
505 if (_hurd_stopped)
506 /* Already stopped. Mark the signal as pending;
507 when resumed, we will notice it and stop again. */
508 mark_pending ();
509 else
510 suspend ();
511 __spin_unlock (&ss->lock);
512 reply ();
513 return;
516 if (handler == SIG_DFL)
517 /* Figure out the default action for this signal. */
518 switch (signo)
520 case 0:
521 /* A sig_post msg with SIGNO==0 is sent to
522 tell us to check for pending signals. */
523 act = ignore;
524 break;
526 case SIGTTIN:
527 case SIGTTOU:
528 case SIGSTOP:
529 case SIGTSTP:
530 act = stop;
531 break;
533 case SIGCONT:
534 case SIGIO:
535 case SIGURG:
536 case SIGCHLD:
537 case SIGWINCH:
538 act = ignore;
539 break;
541 case SIGQUIT:
542 case SIGILL:
543 case SIGTRAP:
544 case SIGIOT:
545 case SIGEMT:
546 case SIGFPE:
547 case SIGBUS:
548 case SIGSEGV:
549 case SIGSYS:
550 act = core;
551 break;
553 case SIGINFO:
554 if (_hurd_pgrp == _hurd_pid)
556 /* We are the process group leader. Since there is no
557 user-specified handler for SIGINFO, we use a default one
558 which prints something interesting. We use the normal
559 handler mechanism instead of just doing it here to avoid
560 the signal thread faulting or blocking in this
561 potentially hairy operation. */
562 act = handle;
563 handler = _hurd_siginfo_handler;
565 else
566 act = ignore;
567 break;
569 default:
570 act = term;
571 break;
573 else if (handler == SIG_IGN)
574 act = ignore;
575 else
576 act = handle;
578 if (__sigmask (signo) & STOPSIGS)
579 /* Stop signals clear a pending SIGCONT even if they
580 are handled or ignored (but not if preempted). */
581 ss->pending &= ~sigmask (SIGCONT);
582 else
584 if (signo == SIGCONT)
585 /* Even if handled or ignored (but not preempted), SIGCONT clears
586 stop signals and resumes the process. */
587 ss->pending &= ~STOPSIGS;
589 if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
591 /* Resume the process from being stopped. */
592 thread_t *threads;
593 mach_msg_type_number_t nthreads, i;
594 error_t err;
595 /* Tell the proc server we are continuing. */
596 __USEPORT (PROC, __proc_mark_cont (port));
597 /* Fetch ports to all our threads and resume them. */
598 err = __task_threads (__mach_task_self (), &threads, &nthreads);
599 assert_perror (err);
600 for (i = 0; i < nthreads; ++i)
602 if (threads[i] != _hurd_msgport_thread &&
603 (act != handle || threads[i] != ss->thread))
604 __thread_resume (threads[i]);
605 __mach_port_deallocate (__mach_task_self (), threads[i]);
607 __vm_deallocate (__mach_task_self (),
608 (vm_address_t) threads,
609 nthreads * sizeof *threads);
610 _hurd_stopped = 0;
611 /* The thread that will run the handler is already suspended. */
612 ss_suspended = 1;
617 if (_hurd_orphaned && act == stop &&
618 (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
619 __sigmask (SIGTSTP))))
621 /* If we would ordinarily stop for a job control signal, but we are
622 orphaned so noone would ever notice and continue us again, we just
623 quietly die, alone and in the dark. */
624 sigcode = signo;
625 signo = SIGKILL;
626 act = term;
629 /* Handle receipt of a blocked signal, or any signal while stopped.
630 It matters that we test ACT first here, because we must never pass
631 SIGNO==0 to __sigismember. */
632 if ((act != ignore && __sigismember (&ss->blocked, signo)) ||
633 (signo != SIGKILL && _hurd_stopped))
635 mark_pending ();
636 act = ignore;
639 /* Perform the chosen action for the signal. */
640 switch (act)
642 case stop:
643 if (_hurd_stopped)
644 /* We are already stopped, but receiving an untraced stop
645 signal. Instead of resuming and suspending again, just
646 notify the proc server of the new stop signal. */
647 __USEPORT (PROC, __proc_mark_stop (port, signo));
648 else
649 /* Suspend the process. */
650 suspend ();
651 break;
653 case ignore:
654 /* Nobody cares about this signal. */
655 break;
657 case term: /* Time to die. */
658 case core: /* And leave a rotting corpse. */
659 nirvana:
660 /* Have the proc server stop all other threads in our task. */
661 __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
662 /* No more user instructions will be executed.
663 The signal can now be considered delivered. */
664 reply ();
665 /* Abort all server operations now in progress. */
666 abort_all_rpcs (signo, &thread_state, 0);
669 int status = W_EXITCODE (0, signo);
670 /* Do a core dump if desired. Only set the wait status bit saying we
671 in fact dumped core if the operation was actually successful. */
672 if (act == core && write_corefile (signo, sigcode, sigerror))
673 status |= WCOREFLAG;
674 /* Tell proc how we died and then stick the saber in the gut. */
675 _hurd_exit (status);
676 /* NOTREACHED */
679 case handle:
680 /* Call a handler for this signal. */
682 struct sigcontext *scp;
683 int wait_for_reply, state_changed;
685 /* Stop the thread and abort its pending RPC operations. */
686 if (! ss_suspended)
687 __thread_suspend (ss->thread);
689 /* Abort the thread's kernel context, so any pending message send
690 or receive completes immediately or aborts. If an interruptible
691 RPC is in progress, abort_rpcs will do this. But we must always
692 do it before fetching the thread's state, because
693 thread_get_state is never kosher before thread_abort. */
694 abort_thread (ss, &thread_state, NULL, 0, 0);
696 wait_for_reply = (abort_rpcs (ss, signo, &thread_state, &state_changed,
697 &reply_port, reply_port_type, untraced)
698 != MACH_PORT_NULL);
700 if (ss->critical_section)
702 /* The thread is in a critical section. Mark the signal as
703 pending. When it finishes the critical section, it will
704 check for pending signals. */
705 mark_pending ();
706 assert (! state_changed);
707 __thread_resume (ss->thread);
708 break;
711 /* Call the machine-dependent function to set the thread up
712 to run the signal handler, and preserve its old context. */
713 scp = _hurd_setup_sighandler (ss, handler,
714 signo, sigcode,
715 wait_for_reply, &thread_state);
716 if (scp == NULL)
718 /* We got a fault setting up the stack frame for the handler.
719 Nothing to do but die; BSD gets SIGILL in this case. */
720 sigcode = signo; /* XXX ? */
721 signo = SIGILL;
722 act = core;
723 goto nirvana;
726 /* Set the machine-independent parts of the signal context. */
728 scp->sc_error = sigerror;
730 /* Fetch the thread variable for the MiG reply port,
731 and set it to MACH_PORT_NULL. */
732 mach_port_t *loc = interrupted_reply_port_location (&thread_state);
733 if (loc)
735 scp->sc_reply_port = *loc;
736 *loc = MACH_PORT_NULL;
738 else
739 scp->sc_reply_port = MACH_PORT_NULL;
742 /* Block SIGNO and requested signals while running the handler. */
743 scp->sc_mask = ss->blocked;
744 ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
746 /* Save the intr_port in use by the interrupted code,
747 and clear the cell before running the trampoline. */
748 scp->sc_intr_port = ss->intr_port;
749 ss->intr_port = MACH_PORT_NULL;
751 /* Start the thread running the handler (or possibly waiting for an
752 RPC reply before running the handler). */
753 __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
754 (natural_t *) &thread_state.basic,
755 MACHINE_THREAD_STATE_COUNT);
756 __thread_resume (ss->thread);
757 thread_state.set = 0; /* Everything we know is now wrong. */
758 break;
762 /* The signal has either been ignored or is now being handled. We can
763 consider it delivered and reply to the killer. The exception is
764 signal 0, which can be sent by a user thread to make us check for
765 pending signals. In that case we want to deliver the pending signals
766 before replying. */
767 if (signo != 0)
768 reply ();
770 /* We get here unless the signal was fatal. We still hold SS->lock.
771 Check for pending signals, and loop to post them. */
772 #define PENDING (!_hurd_stopped && (pending = ss->pending & ~ss->blocked))
773 if (PENDING)
775 pending:
776 for (signo = 1; signo < NSIG; ++signo)
777 if (__sigismember (&pending, signo))
779 __sigdelset (&ss->pending, signo);
780 sigcode = ss->pending_data[signo].code;
781 sigerror = ss->pending_data[signo].error;
782 __spin_unlock (&ss->lock);
783 goto post_signal;
787 /* No pending signals left undelivered for this thread.
788 If we were sent signal 0, we need to check for pending
789 signals for all threads. */
790 if (signo == 0)
792 __spin_unlock (&ss->lock);
793 __mutex_lock (&_hurd_siglock);
794 for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
796 __spin_lock (&ss->lock);
797 if (PENDING)
798 goto pending;
799 __spin_unlock (&ss->lock);
801 __mutex_unlock (&_hurd_siglock);
803 else
805 /* No more signals pending; SS->lock is still locked.
806 Wake up any sigsuspend call that is blocking SS->thread. */
807 if (ss->suspended != MACH_PORT_NULL)
809 /* There is a sigsuspend waiting. Tell it to wake up. */
810 error_t err;
811 mach_msg_header_t msg;
812 err = __mach_port_insert_right (__mach_task_self (),
813 ss->suspended, ss->suspended,
814 MACH_MSG_TYPE_MAKE_SEND);
815 assert_perror (err);
816 msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MOVE_SEND, 0);
817 msg.msgh_remote_port = ss->suspended;
818 msg.msgh_local_port = MACH_PORT_NULL;
819 /* These values do not matter. */
820 msg.msgh_id = 8675309; /* Jenny, Jenny. */
821 msg.msgh_seqno = 17; /* Random. */
822 ss->suspended = MACH_PORT_NULL;
823 err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
824 MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
825 MACH_PORT_NULL);
826 assert_perror (err);
828 __spin_unlock (&ss->lock);
831 /* All pending signals delivered to all threads.
832 Now we can send the reply message even for signal 0. */
833 reply ();
836 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
837 Returns zero if so, otherwise the error code to return to the sender. */
839 static error_t
840 signal_allowed (int signo, mach_port_t refport)
842 if (signo < 0 || signo >= NSIG)
843 return EINVAL;
845 if (refport == __mach_task_self ())
846 /* Can send any signal. */
847 goto win;
849 /* Avoid needing to check for this below. */
850 if (refport == MACH_PORT_NULL)
851 return EPERM;
853 switch (signo)
855 case SIGINT:
856 case SIGQUIT:
857 case SIGTSTP:
858 case SIGHUP:
859 case SIGINFO:
860 case SIGTTIN:
861 case SIGTTOU:
862 /* Job control signals can be sent by the controlling terminal. */
863 if (__USEPORT (CTTYID, port == refport))
864 goto win;
865 break;
867 case SIGCONT:
869 /* A continue signal can be sent by anyone in the session. */
870 mach_port_t sessport;
871 if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
873 __mach_port_deallocate (__mach_task_self (), sessport);
874 if (refport == sessport)
875 goto win;
878 break;
880 case SIGIO:
881 case SIGURG:
883 /* Any io object a file descriptor refers to might send us
884 one of these signals using its async ID port for REFPORT.
886 This is pretty wide open; it is not unlikely that some random
887 process can at least open for reading something we have open,
888 get its async ID port, and send us a spurious SIGIO or SIGURG
889 signal. But BSD is actually wider open than that!--you can set
890 the owner of an io object to any process or process group
891 whatsoever and send them gratuitous signals.
893 Someday we could implement some reasonable scheme for
894 authorizing SIGIO and SIGURG signals properly. */
896 int d;
897 __mutex_lock (&_hurd_dtable_lock);
898 for (d = 0; (unsigned int) d < (unsigned int) _hurd_dtablesize; ++d)
900 struct hurd_userlink ulink;
901 io_t port;
902 mach_port_t asyncid;
903 if (_hurd_dtable[d] == NULL)
904 continue;
905 port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
906 if (! __io_get_icky_async_id (port, &asyncid))
908 if (refport == asyncid)
909 /* Break out of the loop on the next iteration. */
910 d = -1;
911 __mach_port_deallocate (__mach_task_self (), asyncid);
913 _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
915 /* If we found a lucky winner, we've set D to -1 in the loop. */
916 if (d < 0)
917 goto win;
921 /* If this signal is legit, we have done `goto win' by now.
922 When we return the error, mig deallocates REFPORT. */
923 return EPERM;
925 win:
926 /* Deallocate the REFPORT send right; we are done with it. */
927 __mach_port_deallocate (__mach_task_self (), refport);
929 return 0;
932 /* Implement the sig_post RPC from <hurd/msg.defs>;
933 sent when someone wants us to get a signal. */
934 kern_return_t
935 _S_msg_sig_post (mach_port_t me,
936 mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
937 int signo,
938 mach_port_t refport)
940 error_t err;
942 if (err = signal_allowed (signo, refport))
943 return err;
945 /* Post the signal to the designated signal-receiving thread. This will
946 reply when the signal can be considered delivered. */
947 _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
948 signo, 0, 0, reply_port, reply_port_type,
949 0); /* Stop if traced. */
951 return MIG_NO_REPLY; /* Already replied. */
954 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
955 sent when the debugger wants us to really get a signal
956 even if we are traced. */
957 kern_return_t
958 _S_msg_sig_post_untraced (mach_port_t me,
959 mach_port_t reply_port,
960 mach_msg_type_name_t reply_port_type,
961 int signo,
962 mach_port_t refport)
964 error_t err;
966 if (err = signal_allowed (signo, refport))
967 return err;
969 /* Post the signal to the designated signal-receiving thread. This will
970 reply when the signal can be considered delivered. */
971 _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
972 signo, 0, 0, reply_port, reply_port_type,
973 1); /* Untraced flag. */
975 return MIG_NO_REPLY; /* Already replied. */
978 extern void __mig_init (void *);
980 #include <mach/task_special_ports.h>
982 /* Initialize the message port and _hurd_sigthread and start the signal
983 thread. */
985 void
986 _hurdsig_init (void)
988 error_t err;
989 vm_size_t stacksize;
991 __mutex_init (&_hurd_siglock);
993 if (err = __mach_port_allocate (__mach_task_self (),
994 MACH_PORT_RIGHT_RECEIVE,
995 &_hurd_msgport))
996 __libc_fatal ("hurd: Can't create message port receive right\n");
998 /* Make a send right to the signal port. */
999 if (err = __mach_port_insert_right (__mach_task_self (),
1000 _hurd_msgport,
1001 _hurd_msgport,
1002 MACH_MSG_TYPE_MAKE_SEND))
1003 __libc_fatal ("hurd: Can't create send right to message port\n");
1005 /* Set the default thread to receive task-global signals
1006 to this one, the main (first) user thread. */
1007 _hurd_sigthread = __mach_thread_self ();
1009 /* Start the signal thread listening on the message port. */
1011 if (err = __thread_create (__mach_task_self (), &_hurd_msgport_thread))
1012 __libc_fatal ("hurd: Can't create signal thread\n");
1014 stacksize = __vm_page_size * 4; /* Small stack for signal thread. */
1015 if (err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1016 _hurd_msgport_receive,
1017 (vm_address_t *) &__hurd_sigthread_stack_base,
1018 &stacksize))
1019 __libc_fatal ("hurd: Can't setup signal thread\n");
1021 __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1022 __hurd_sigthread_variables =
1023 malloc (__hurd_threadvar_max * sizeof (unsigned long int));
1024 if (__hurd_sigthread_variables == NULL)
1025 __libc_fatal ("hurd: Can't allocate thread variables for signal thread\n");
1027 /* Reinitialize the MiG support routines so they will use a per-thread
1028 variable for the cached reply port. */
1029 __mig_init ((void *) __hurd_sigthread_stack_base);
1031 if (err = __thread_resume (_hurd_msgport_thread))
1032 __libc_fatal ("hurd: Can't resume signal thread\n");
1034 #if 0 /* Don't confuse poor gdb. */
1035 /* Receive exceptions on the signal port. */
1036 __task_set_special_port (__mach_task_self (),
1037 TASK_EXCEPTION_PORT, _hurd_msgport);
1038 #endif
1040 \f /* XXXX */
1041 /* Reauthenticate with the proc server. */
1043 static void
1044 reauth_proc (mach_port_t new)
1046 mach_port_t ref, ignore;
1048 ref = __mach_reply_port ();
1049 if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1050 __proc_reauthenticate (port, ref,
1051 MACH_MSG_TYPE_MAKE_SEND) ||
1052 __auth_user_authenticate (new, port, ref,
1053 MACH_MSG_TYPE_MAKE_SEND,
1054 &ignore))
1055 && ignore != MACH_PORT_NULL)
1056 __mach_port_deallocate (__mach_task_self (), ignore);
1057 __mach_port_destroy (__mach_task_self (), ref);
1059 (void) &reauth_proc; /* Silence compiler warning. */
1061 text_set_element (_hurd_reauth_hook, reauth_proc);
1063 /* Like `getenv', but safe for the signal thread to run.
1064 If the environment is trashed, this will just return NULL. */
1066 const char *
1067 _hurdsig_getenv (const char *variable)
1069 if (_hurdsig_catch_fault (SIGSEGV))
1070 /* We bombed in getenv. */
1071 return NULL;
1072 else
1074 const char *value = getenv (variable);
1075 /* Fault now if VALUE is a bogus string. */
1076 (void) strlen (value);
1077 _hurdsig_end_catch_fault ();
1078 return value;