4f8a832a47713a4dc4255ff75e885f80db1a8b50
[kopensolaris-gnu/glibc.git] / hurd / hurdsig.c
1 /* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU 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.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 Library General Public License for more details.
13
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.  */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <gnu-stabs.h>
22 #include <hurd.h>
23 #include <hurd/signal.h>
24 #include <cthreads.h>           /* For `struct mutex'.  */
25 #include <string.h>
26 #include "hurdfault.h"
27 #include "hurdmalloc.h"         /* XXX */
28
29 const char *_hurdsig_getenv (const char *);
30
31 struct mutex _hurd_siglock;
32 int _hurd_stopped;
33
34 /* Port that receives signals and other miscellaneous messages.  */
35 mach_port_t _hurd_msgport;
36
37 /* Thread listening on it.  */
38 thread_t _hurd_msgport_thread;
39
40 /* Thread which receives task-global signals.  */
41 thread_t _hurd_sigthread;
42
43 /* Linked-list of per-thread signal state.  */
44 struct hurd_sigstate *_hurd_sigstates;
45 \f
46 static void
47 default_sigaction (struct sigaction actions[NSIG])
48 {
49   int signo;
50
51   __sigemptyset (&actions[0].sa_mask);
52   actions[0].sa_flags = SA_RESTART;
53   actions[0].sa_handler = SIG_DFL;
54
55   for (signo = 1; signo < NSIG; ++signo)
56     actions[signo] = actions[0];
57 }
58
59 struct hurd_sigstate *
60 _hurd_thread_sigstate (thread_t thread)
61 {
62   struct hurd_sigstate *ss;
63   __mutex_lock (&_hurd_siglock);
64   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
65     if (ss->thread == thread)
66       break;
67   if (ss == NULL)
68     {
69       ss = malloc (sizeof (*ss));
70       if (ss == NULL)
71         __libc_fatal ("hurd: Can't allocate thread sigstate\n");
72       ss->thread = thread;
73       __mutex_init (&ss->lock);
74
75       /* Initialze default state.  */
76       __sigemptyset (&ss->blocked);
77       __sigemptyset (&ss->pending);
78       memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
79       ss->suspended = 0;
80 #ifdef noteven
81       __condition_init (&ss->arrived);
82 #endif
83       ss->intr_port = MACH_PORT_NULL;
84       ss->context = NULL;
85
86       /* Initialize the sigaction vector from the default signal receiving
87          thread's state, and its from the system defaults.  */
88       if (thread == _hurd_sigthread)
89         default_sigaction (ss->actions);
90       else
91         {
92           struct hurd_sigstate *s;
93           for (s = _hurd_sigstates; s != NULL; s = s->next)
94             if (s->thread == _hurd_sigthread)
95               break;
96           if (s)
97             {
98               __mutex_lock (&s->lock);
99               memcpy (ss->actions, s->actions, sizeof (s->actions));
100               __mutex_unlock (&s->lock);
101             }
102           else
103             default_sigaction (ss->actions);
104         }
105
106       ss->next = _hurd_sigstates;
107       _hurd_sigstates = ss;
108     }
109   __mutex_lock (&ss->lock);
110   __mutex_unlock (&_hurd_siglock);
111   return ss;
112 }
113 \f
114 /* Signal delivery itself is on this page.  */
115
116 #include <hurd/fd.h>
117 #include <hurd/core.h>
118 #include <hurd/paths.h>
119 #include <setjmp.h>
120 #include <fcntl.h>
121 #include <sys/wait.h>
122 #include "thread_state.h"
123 #include <hurd/msg_server.h>
124 #include <hurd/msg_reply.h>     /* For __sig_post_reply.  */
125 #include <assert.h>
126 #include <hurd/interrupt.h>
127
128 int _hurd_core_limit;   /* XXX */
129
130 /* Call the core server to mummify us before we die.
131    Returns nonzero if a core file was written.  */
132 static int
133 write_corefile (int signo, int sigcode, int sigerror)
134 {
135   error_t err;
136   mach_port_t coreserver;
137   file_t file, coredir;
138   const char *name;
139
140   /* XXX RLIMIT_CORE:
141      When we have a protocol to make the server return an error
142      for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE
143      value in place of the RLIMIT_FSIZE value.  */
144
145   /* First get a port to the core dumping server.  */
146   coreserver = MACH_PORT_NULL;
147   name = _hurdsig_getenv ("CORESERVER");
148   if (name != NULL)
149     coreserver = __file_name_lookup (name, 0, 0);
150   if (coreserver == MACH_PORT_NULL)
151     coreserver = __file_name_lookup (_SERVERS_CORE, 0, 0);
152   if (coreserver == MACH_PORT_NULL)
153     return 0;
154
155   /* Get a port to the directory where the new core file will reside.  */
156   name = _hurdsig_getenv ("COREFILE");
157   if (name == NULL)
158     name = "core";
159   coredir = __file_name_split (name, (char **) &name);
160   if (coredir == MACH_PORT_NULL)
161     return 0;
162   /* Create the new file, but don't link it into the directory yet.  */
163   if (err = __dir_mkfile (coredir, O_WRONLY|O_CREAT,
164                           0600 & ~_hurd_umask, /* XXX ? */
165                           &file))
166     return 0;
167
168   /* Call the core dumping server to write the core file.  */
169   err = __core_dump_task (coreserver,
170                           __mach_task_self (),
171                           file, _hurdsig_getenv ("GNUTARGET"),
172                           signo, sigcode, sigerror);
173   __mach_port_deallocate (__mach_task_self (), coreserver);
174   if (! err)
175     /* The core dump into FILE succeeded, so now link it into the
176        directory.  */
177     err = __dir_link (file, coredir, name);
178   __mach_port_deallocate (__mach_task_self (), file);
179   __mach_port_deallocate (__mach_task_self (), coredir);
180   return !err;
181 }
182
183
184 /* Send a sig_post reply message if it hasn't already been sent.  */
185 static inline void
186 post_reply (mach_port_t *reply_port, mach_msg_type_name_t reply_port_type,
187             error_t result)
188 {
189   if (reply_port == NULL || *reply_port == MACH_PORT_NULL)
190     return;
191   __sig_post_reply (*reply_port, reply_port_type, result);
192   *reply_port = MACH_PORT_NULL;
193 }
194
195
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
200
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 {
208   if (!(state->set & THREAD_ABORTED))
209     {
210       __thread_abort (ss->thread);
211       /* Clear all thread state flavor set bits, because thread_abort may
212          have changed the state.  */
213       state->set = THREAD_ABORTED;
214     }
215
216   if (reply_port)
217     post_reply (reply_port, reply_port_type, 0);
218
219   machine_get_basic_state (ss->thread, state);
220 }
221
222 /* Find the location of the MiG reply port cell in use by the thread whose
223    state is described by THREAD_STATE.  Make sure that this location can be
224    set without faulting, or else return NULL.  */
225
226 static mach_port_t *
227 interrupted_reply_port_location (struct machine_thread_all_state *thread_state)
228 {
229   mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
230     (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
231
232   if (_hurdsig_catch_fault (SIGSEGV))
233     {
234       assert (_hurdsig_fault_sigcode == (int) portloc);
235       /* Faulted trying to read the stack.  */
236       return NULL;
237     }
238
239   /* Fault now if this pointer is bogus.  */
240   *(volatile mach_port_t *) portloc = *portloc;
241
242   _hurdsig_end_catch_fault ();
243
244   return portloc;
245 }
246
247
248 /* SS->thread is suspended.
249
250    Abort any interruptible RPC operation the thread is doing.
251
252    This uses only the constant member SS->thread and the unlocked, atomically
253    set member SS->intr_port, so no locking is needed.
254
255 If successfully sent an interrupt_operation and therefore the thread should
256    wait for its pending RPC to return (possibly EINTR) before taking the
257    incoming signal, returns the reply port to be received on.  Otherwise
258    returns MACH_PORT_NULL.  */
259
260 static mach_port_t
261 abort_rpcs (struct hurd_sigstate *ss, int signo,
262             struct machine_thread_all_state *state,
263             mach_port_t *reply_port, mach_msg_type_name_t reply_port_type)
264 {
265   mach_port_t msging_port;
266   mach_port_t intr_port;
267
268   intr_port = ss->intr_port;
269   if (intr_port == MACH_PORT_NULL)
270     /* No interruption needs done.  */
271     return 0;
272
273   /* Abort the thread's kernel context, so any pending message send or
274      receive completes immediately or aborts.  */
275   abort_thread (ss, state, reply_port, reply_port_type);
276
277   if (_hurdsig_rcv_interrupted_p (state, &msging_port))
278     {
279       error_t err;
280
281       /* The RPC request message was sent and the thread was waiting for
282          the reply message; now the message receive has been aborted, so
283          the mach_msg_call will return MACH_RCV_INTERRUPTED.  We must tell
284          the server to interrupt the pending operation.  The thread must
285          wait for the reply message before running the signal handler (to
286          guarantee that the operation has finished being interrupted), so
287          our nonzero return tells the trampoline code to finish the message
288          receive operation before running the handler.  */
289
290       err = __interrupt_operation (intr_port);
291
292       if (err)
293         {
294           mach_port_t *reply;
295
296           /* The interrupt didn't work.
297              Destroy the receive right the thread is blocked on.  */
298           __mach_port_destroy (__mach_task_self (), msging_port);
299
300           /* The system call return value register now contains
301              MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
302              call.  Since we have just destroyed the receive right, the
303              retry will fail with MACH_RCV_INVALID_NAME.  Instead, just
304              change the return value here to EINTR so mach_msg will not
305              retry and the EINTR error code will propagate up.  */
306           state->basic.SYSRETURN = EINTR;
307
308           /* If that was the thread's MiG reply port (which I think should
309              always be the case), clear the reply port cell so it won't be
310              reused.  */
311           reply = interrupted_reply_port_location (state);
312           if (reply != NULL && *reply == msging_port)
313             *reply = MACH_PORT_NULL;
314         }
315
316       /* All threads whose RPCs were interrupted by the interrupt_operation
317          call above will retry their RPCs unless we clear SS->intr_port.
318          So we clear it for the thread taking a signal when SA_RESTART is
319          clear, so that its call returns EINTR.  */
320       if (!(ss->actions[signo].sa_flags & SA_RESTART))
321         ss->intr_port = MACH_PORT_NULL;
322
323       return !err;
324     }
325
326   /* One of the following is true:
327
328      1. The RPC has not yet been sent.  The thread will start its operation
329      after the signal has been handled.
330
331      2. The RPC has finished, but not yet cleared SS->intr_port.
332      The thread will clear SS->intr_port after running the handler.
333
334      3. The RPC request message was being sent was aborted.  The mach_msg
335      system call will return MACH_SEND_INTERRUPTED, and HURD_EINTR_RPC will
336      notice the interruption (either retrying the RPC or returning EINTR).  */
337
338   return 0;
339 }
340
341 /* Abort the RPCs being run by all threads but this one;
342    all other threads should be suspended.  */
343 static void
344 abort_all_rpcs (int signo, struct machine_thread_all_state *state)
345 {
346   /* We can just loop over the sigstates.  Any thread doing something
347      interruptible must have one.  We needn't bother locking because all
348      other threads are stopped.  */
349
350   struct hurd_sigstate *ss;
351
352   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
353     if (ss->thread != _hurd_msgport_thread)
354       /* Abort any operation in progress with interrupt_operation.  We
355          record this by putting the reply port into SS->intr_port, or
356          MACH_PORT_NULL if no interruption was done.  We will wait for
357          all the replies below.  */
358       ss->intr_port = abort_rpcs (ss, signo, state, NULL, 0);
359
360   /* Wait for replies from all the successfully interrupted RPCs.  */
361   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
362     if (ss->intr_port != MACH_PORT_NULL)
363       {
364         error_t err;
365         mach_msg_header_t head;
366         err = __mach_msg (&head, MACH_RCV_MSG, 0, sizeof head, ss->intr_port,
367                           MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
368         assert (err == KERN_SUCCESS || err == MACH_RCV_TOO_LARGE);
369       }
370 }
371
372
373 struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
374 struct mutex _hurd_signal_preempt_lock;
375
376 /* Mask of stop signals.  */
377 #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
378                   sigmask (SIGSTOP) | sigmask (SIGTSTP))
379
380 /* Deliver a signal.
381    SS->lock is held on entry and released before return.  */
382 void
383 _hurd_internal_post_signal (struct hurd_sigstate *ss,
384                             int signo, int sigcode, int sigerror,
385                             mach_port_t reply_port,
386                             mach_msg_type_name_t reply_port_type)
387 {
388   struct machine_thread_all_state thread_state;
389   enum { stop, ignore, core, term, handle } act;
390   sighandler_t handler;
391   struct hurd_signal_preempt *pe;
392   sighandler_t (*preempt) (thread_t, int, int) = NULL;
393   sigset_t pending;
394   int ss_suspended;
395
396   /* Reply to this sig_post message.  */
397   inline void reply ()
398     {
399       post_reply (&reply_port, reply_port_type, 0);
400     }
401
402   /* Wake up a sigsuspend call that is blocking SS->thread.  */
403   inline void sigwakeup (void)
404     {
405       if (ss->suspended != MACH_PORT_NULL)
406         {
407           /* There is a sigsuspend waiting.  Tell it to wake up.  */
408           error_t err;
409           mach_msg_header_t msg;
410           err = __mach_port_insert_right (__mach_task_self (),
411                                           ss->suspended, ss->suspended,
412                                           MACH_MSG_TYPE_MAKE_SEND);
413           assert (err == KERN_SUCCESS);
414           msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MOVE_SEND, 0);
415           msg.msgh_remote_port = ss->suspended;
416           msg.msgh_local_port = MACH_PORT_NULL;
417           /* These values do not matter.  */
418           msg.msgh_id = 8675309; /* Jenny, Jenny.  */
419           msg.msgh_seqno = 17;  /* Random.  */
420           ss->suspended = MACH_PORT_NULL;
421           err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
422                             MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
423                             MACH_PORT_NULL);
424           assert (err == MACH_MSG_SUCCESS);
425         }
426       __mutex_unlock (&ss->lock);
427     }
428
429  post_signal:
430
431   thread_state.set = 0;         /* We know nothing.  */
432
433   /* Check for a preempted signal.  */
434   __mutex_lock (&_hurd_signal_preempt_lock);
435   for (pe = _hurd_signal_preempt[signo]; pe != NULL; pe = pe->next)
436     if (sigcode >= pe->first && sigcode <= pe->last)
437       {
438         preempt = pe->handler;
439         break;
440       }
441   __mutex_unlock (&_hurd_signal_preempt_lock);
442
443   handler = SIG_DFL;
444   if (preempt)
445     /* Let the preempting handler examine the thread.
446        If it returns SIG_DFL, we run the normal handler;
447        otherwise we use the handler it returns.  */
448     handler = (*preempt) (ss->thread, signo, sigcode);
449
450   ss_suspended = 0;
451
452   if (handler != SIG_DFL)
453     /* Run the preemption-provided handler.  */
454     act = handle;
455   else
456     {
457       /* No preemption.  Do normal handling.  */
458
459       handler = ss->actions[signo].sa_handler;
460
461       if (handler == SIG_DFL)
462         /* Figure out the default action for this signal.  */
463         switch (signo)
464           {
465           case 0:
466             /* A sig_post msg with SIGNO==0 is sent to
467                tell us to check for pending signals.  */
468             act = ignore;
469             break;
470
471           case SIGTTIN:
472           case SIGTTOU:
473           case SIGSTOP:
474           case SIGTSTP:
475             act = stop;
476             break;
477
478           case SIGCONT:
479           case SIGIO:
480           case SIGURG:
481           case SIGCHLD:
482           case SIGWINCH:
483             act = ignore;
484             break;
485
486           case SIGQUIT:
487           case SIGILL:
488           case SIGTRAP:
489           case SIGIOT:
490           case SIGEMT:
491           case SIGFPE:
492           case SIGBUS:
493           case SIGSEGV:
494           case SIGSYS:
495             act = core;
496             break;
497
498           case SIGINFO:
499             if (_hurd_pgrp == _hurd_pid)
500               {
501                 /* We are the process group leader.  Since there is no
502                    user-specified handler for SIGINFO, we use a default one
503                    which prints something interesting.  We use the normal
504                    handler mechanism instead of just doing it here to avoid
505                    the signal thread faulting or blocking in this
506                    potentially hairy operation.  */
507                 act = handle;
508                 handler = _hurd_siginfo_handler;
509               }
510             else
511               act = ignore;
512             break;
513
514           default:
515             act = term;
516             break;
517           }
518       else if (handler == SIG_IGN)
519         act = ignore;
520       else
521         act = handle;
522
523       if (sigmask (signo) & STOPSIGS)
524         /* Stop signals clear a pending SIGCONT even if they
525            are handled or ignored (but not if preempted).  */
526         ss->pending &= ~sigmask (SIGCONT);
527       else if (signo == SIGCONT)
528         {
529           /* Even if handled or ignored (but not preempted),
530              SIGCONT clears stop signals and resumes the process.  */
531           ss->pending &= ~STOPSIGS;
532           if (_hurd_stopped)
533             {
534               thread_t *threads;
535               unsigned int nthreads, i;
536               error_t err;
537               /* Tell the proc server we are continuing.  */
538               __USEPORT (PROC, __proc_mark_cont (port));
539               /* Fetch ports to all our threads and resume them.  */
540               err = __task_threads (__mach_task_self (), &threads, &nthreads);
541               assert (! err);
542               for (i = 0; i < nthreads; ++i)
543                 {
544                   if (threads[i] != _hurd_msgport_thread &&
545                       (act != handle || threads[i] != ss->thread))
546                     __thread_resume (threads[i]);
547                   __mach_port_deallocate (__mach_task_self (), threads[i]);
548                 }
549               __vm_deallocate (__mach_task_self (),
550                                (vm_address_t) threads,
551                                nthreads * sizeof *threads);
552               _hurd_stopped = 0;
553               /* The thread that will run the handler is already suspended.  */
554               ss_suspended = 1;
555             }
556         }
557     }
558
559   if (_hurd_orphaned && act == stop &&
560       (signo & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
561                 __sigmask (SIGTSTP))))
562     {
563       /* If we would ordinarily stop for a job control signal, but we are
564          orphaned so noone would ever notice and continue us again, we just
565          quietly die, alone and in the dark.  */
566       sigcode = signo;
567       signo = SIGKILL;
568       act = term;
569     }
570
571   /* Handle receipt of a blocked signal.  */
572   if ((__sigismember (&ss->blocked, signo) && act != ignore) ||
573       (signo != SIGKILL && _hurd_stopped))
574     {
575       __sigaddset (&ss->pending, signo);
576       /* Save the code to be given to the handler when SIGNO is unblocked.  */
577       ss->pending_data[signo].code = sigcode;
578       ss->pending_data[signo].error = sigerror;
579       act = ignore;
580     }
581
582   /* Perform the chosen action for the signal.  */
583   switch (act)
584     {
585     case stop:
586       if (! _hurd_stopped)
587         {
588           /* Stop all other threads and mark ourselves stopped.  */
589           __USEPORT (PROC,
590                      ({
591                        /* Hold the siglock while stopping other threads to be
592                           sure it is not held by another thread afterwards.  */
593                        __mutex_unlock (&ss->lock);
594                        __mutex_lock (&_hurd_siglock);
595                        __proc_dostop (port, _hurd_msgport_thread);
596                        __mutex_unlock (&_hurd_siglock);
597                        abort_all_rpcs (signo, &thread_state);
598                        __proc_mark_stop (port, signo);
599                      }));
600           _hurd_stopped = 1;
601         }
602
603       __mutex_lock (&ss->lock);
604       sigwakeup ();             /* Wake up sigsuspend.  */
605       break;
606
607     case ignore:
608       /* Nobody cares about this signal.  */
609       break;
610
611     case term:                  /* Time to die.  */
612     case core:                  /* And leave a rotting corpse.  */
613     nirvana:
614       __mutex_unlock (&ss->lock);
615       /* Have the proc server stop all other threads in our task.  */
616       __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
617       /* No more user instructions will be executed.
618          The signal can now be considered delivered.  */
619       reply ();
620       /* Abort all server operations now in progress.  */
621       abort_all_rpcs (signo, &thread_state);
622
623       {
624         int status = W_EXITCODE (0, signo);
625         /* Do a core dump if desired.  Only set the wait status bit saying we
626            in fact dumped core if the operation was actually successful.  */
627         if (act == core && write_corefile (signo, sigcode, sigerror))
628           status |= WCOREFLAG;
629         /* Tell proc how we died and then stick the saber in the gut.  */
630         _hurd_exit (status);
631         /* NOTREACHED */
632       }
633
634     case handle:
635       /* Call a handler for this signal.  */
636       {
637         struct sigcontext *scp;
638         int wait_for_reply;
639
640         /* Stop the thread and abort its pending RPC operations.  */
641         if (! ss_suspended)
642           __thread_suspend (ss->thread);
643         wait_for_reply = (abort_rpcs (ss, signo, &thread_state,
644                                       &reply_port, reply_port_type)
645                           != MACH_PORT_NULL);
646
647         /* Call the machine-dependent function to set the thread up
648            to run the signal handler, and preserve its old context.  */
649         scp = _hurd_setup_sighandler (ss, handler,
650                                       signo, sigcode,
651                                       wait_for_reply, &thread_state);
652         if (scp == NULL)
653           {
654             /* We got a fault setting up the stack frame for the handler.
655                Nothing to do but die; BSD gets SIGILL in this case.  */
656             sigcode = signo;    /* XXX ? */
657             signo = SIGILL;
658             act = core;
659             goto nirvana;
660           }
661
662         /* Set the machine-independent parts of the signal context.  */
663
664         scp->sc_error = sigerror;
665         {
666           /* Fetch the thread variable for the MiG reply port,
667              and set it to MACH_PORT_NULL.  */
668           mach_port_t *loc = interrupted_reply_port_location (&thread_state);
669           if (loc)
670             {
671               scp->sc_reply_port = *loc;
672               *loc = MACH_PORT_NULL;
673             }
674           else
675             scp->sc_reply_port = MACH_PORT_NULL;
676         }
677
678         /* Block SIGNO and requested signals while running the handler.  */
679         scp->sc_mask = ss->blocked;
680         ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
681
682         /* Save the intr_port in use by the interrupted code,
683            and clear the cell before running the trampoline.  */
684         scp->sc_intr_port = ss->intr_port;
685         ss->intr_port = MACH_PORT_NULL;
686
687         /* Start the thread running the handler (or possibly waiting for an
688            RPC reply before running the handler).  */
689         __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
690                             (int *) &thread_state.basic,
691                             MACHINE_THREAD_STATE_COUNT);
692         __thread_resume (ss->thread);
693         thread_state.set = 0;   /* Everything we know is now wrong.  */
694         break;
695       }
696     }
697
698   /* The signal has either been ignored or is now being handled.  We can
699      consider it delivered and reply to the killer.  The exception is
700      signal 0, which can be sent by a user thread to make us check for
701      pending signals.  In that case we want to deliver the pending signals
702      before replying.  */
703   if (signo != 0)
704     reply ();
705
706   /* We get here only if we are handling or ignoring the signal;
707      otherwise we are stopped or dead by now.  We still hold SS->lock.
708      Check for pending signals, and loop to post them.  */
709 #define PENDING (!_hurd_stopped && (pending = ss->pending & ~ss->blocked))
710   if (PENDING)
711     {
712     pending:
713       for (signo = 1; signo < NSIG; ++signo)
714         if (__sigismember (&pending, signo))
715           {
716             __sigdelset (&ss->pending, signo);
717             sigcode = ss->pending_data[signo].code;
718             sigerror = ss->pending_data[signo].error;
719             goto post_signal;
720           }
721     }
722
723   /* No more signals pending; SS->lock is still locked.  */
724   sigwakeup ();
725
726   /* No pending signals left undelivered for this thread.
727      If we were sent signal 0, we need to check for pending
728      signals for all threads.  */
729   if (signo == 0)
730     {
731       __mutex_lock (&_hurd_siglock);
732       for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
733         {
734           __mutex_lock (&ss->lock);
735           if (PENDING)
736             goto pending;
737           __mutex_unlock (&ss->lock);
738         }
739       __mutex_unlock (&_hurd_siglock);
740     }
741
742   /* All pending signals delivered to all threads.
743      Now we can send the reply message even for signal 0.  */
744   reply ();
745 }
746
747 /* Implement the sig_post RPC from <hurd/msg.defs>;
748    sent when someone wants us to get a signal.  */
749 kern_return_t
750 _S_sig_post (mach_port_t me,
751              mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
752              int signo,
753              mach_port_t refport)
754 {
755   struct hurd_sigstate *ss;
756
757   if (signo < 0 || signo >= NSIG)
758     return EINVAL;
759
760   if (refport == __mach_task_self ())
761     /* Can send any signal.  */
762     goto win;
763
764   /* Avoid needing to check for this below.  */
765   if (refport == MACH_PORT_NULL)
766     return EPERM;
767
768   switch (signo)
769     {
770     case SIGINT:
771     case SIGQUIT:
772     case SIGTSTP:
773     case SIGHUP:
774     case SIGINFO:
775     case SIGTTIN:
776     case SIGTTOU:
777       /* Job control signals can be sent by the controlling terminal.  */
778       if (__USEPORT (CTTYID, port == refport))
779         goto win;
780       break;
781
782     case SIGCONT:
783       {
784         /* A continue signal can be sent by anyone in the session.  */
785         mach_port_t sessport;
786         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
787           { 
788             __mach_port_deallocate (__mach_task_self (), sessport);
789             if (refport == sessport)
790               goto win;
791           }
792       }
793       break;
794
795     case SIGIO:
796     case SIGURG:
797       {
798         /* Any io object a file descriptor refers to might send us
799            one of these signals using its async ID port for REFPORT.
800
801            This is pretty wide open; it is not unlikely that some random
802            process can at least open for reading something we have open,
803            get its async ID port, and send us a spurious SIGIO or SIGURG
804            signal.  But BSD is actually wider open than that!--you can set
805            the owner of an io object to any process or process group
806            whatsoever and send them gratuitous signals.
807
808            Someday we could implement some reasonable scheme for
809            authorizing SIGIO and SIGURG signals properly.  */
810
811         int d;
812         __mutex_lock (&_hurd_dtable_lock);
813         for (d = 0; (unsigned int) d < (unsigned int) _hurd_dtablesize; ++d)
814           {
815             struct hurd_userlink ulink;
816             io_t port;
817             mach_port_t asyncid;
818             if (_hurd_dtable[d] == NULL)
819               continue;
820             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
821             if (! __io_get_icky_async_id (port, &asyncid))
822               {
823                 if (refport == asyncid)
824                   /* Break out of the loop on the next iteration.  */
825                   d = -1;
826                 __mach_port_deallocate (__mach_task_self (), asyncid);
827               }
828             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
829           }
830         /* If we found a lucky winner, we've set D to -1 in the loop.  */
831         if (d < 0)
832           goto win;
833       }
834     }
835
836   /* If this signal is legit, we have done `goto win' by now.
837      When we return the error, mig deallocates REFPORT.  */
838   return EPERM;
839
840  win:
841   /* Deallocate the REFPORT send right; we are done with it.  */
842   __mach_port_deallocate (__mach_task_self (), refport);
843
844   /* Get a hold of the designated signal-receiving thread.  */
845   ss = _hurd_thread_sigstate (_hurd_sigthread);
846
847   /* Post the signal; this will reply when the signal can be considered
848      delivered.  */
849   _hurd_internal_post_signal (ss, signo, 0, 0, reply_port, reply_port_type);
850
851   return MIG_NO_REPLY;          /* Already replied.  */
852 }
853 \f
854 extern void __mig_init (void *);
855
856 #include <mach/task_special_ports.h>
857
858 /* Initialize the message port and _hurd_sigthread and start the signal
859    thread.  */
860
861 void
862 _hurdsig_init (void)
863 {
864   error_t err;
865   vm_size_t stacksize;
866
867   __mutex_init (&_hurd_siglock);
868
869   if (err = __mach_port_allocate (__mach_task_self (),
870                                   MACH_PORT_RIGHT_RECEIVE,
871                                   &_hurd_msgport))
872     __libc_fatal ("hurd: Can't create message port receive right\n");
873   
874   /* Make a send right to the signal port.  */
875   if (err = __mach_port_insert_right (__mach_task_self (),
876                                       _hurd_msgport,
877                                       _hurd_msgport,
878                                       MACH_MSG_TYPE_MAKE_SEND))
879     __libc_fatal ("hurd: Can't create send right to message port\n");
880
881   /* Set the default thread to receive task-global signals
882      to this one, the main (first) user thread.  */
883   _hurd_sigthread = __mach_thread_self ();
884
885   /* Start the signal thread listening on the message port.  */
886
887   if (err = __thread_create (__mach_task_self (), &_hurd_msgport_thread))
888     __libc_fatal ("hurd: Can't create signal thread\n");
889
890   stacksize = __vm_page_size * 4; /* Small stack for signal thread.  */
891   if (err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
892                                  _hurd_msgport_receive,
893                                  (vm_address_t *) &__hurd_sigthread_stack_base,
894                                  &stacksize))
895     __libc_fatal ("hurd: Can't setup signal thread\n");
896
897   __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
898   __hurd_sigthread_variables =
899     malloc (__hurd_threadvar_max * sizeof (unsigned long int));
900   if (__hurd_sigthread_variables == NULL)
901     __libc_fatal ("hurd: Can't allocate thread variables for signal thread\n");
902
903   /* Reinitialize the MiG support routines so they will use a per-thread
904      variable for the cached reply port.  */
905   __mig_init ((void *) __hurd_sigthread_stack_base);
906
907   if (err = __thread_resume (_hurd_msgport_thread))
908     __libc_fatal ("hurd: Can't resume signal thread\n");
909     
910 #if 0                           /* Don't confuse poor gdb.  */
911   /* Receive exceptions on the signal port.  */
912   __task_set_special_port (__mach_task_self (),
913                            TASK_EXCEPTION_PORT, _hurd_msgport);
914 #endif
915 }
916 \f                               /* XXXX */
917 /* Reauthenticate with the proc server.  */
918
919 static void
920 reauth_proc (mach_port_t new)
921 {
922   mach_port_t ref, ignore;
923
924   ref = __mach_reply_port ();
925   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
926                        __proc_reauthenticate (port, ref,
927                                               MACH_MSG_TYPE_MAKE_SEND) ||
928                        __auth_user_authenticate (new, port, ref,
929                                                  MACH_MSG_TYPE_MAKE_SEND,
930                                                  &ignore))
931       && ignore != MACH_PORT_NULL)
932     __mach_port_deallocate (__mach_task_self (), ignore);
933   __mach_port_destroy (__mach_task_self (), ref);
934
935   (void) &reauth_proc;          /* Silence compiler warning.  */
936 }
937 text_set_element (__hurd_reauth_hook, reauth_proc);
938 \f
939 /* Like `getenv', but safe for the signal thread to run.
940    If the environment is trashed, this will just return NULL.  */
941
942 const char *
943 _hurdsig_getenv (const char *variable)
944 {
945   if (_hurdsig_catch_fault (SIGSEGV))
946     /* We bombed in getenv.  */
947     return NULL;
948   else
949     {
950       const char *value = getenv (variable);
951       /* Fault now if VALUE is a bogus string.  */
952       (void) strlen (value);
953       _hurdsig_end_catch_fault ();
954       return value;
955     }
956 }