(_hurd_internal_post_signal): In stopping orphan test, take sigmask of
[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 MACH_PORT_NULL;
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 ? MACH_PORT_NULL : msging_port;
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 MACH_PORT_NULL;
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         if (err != MACH_RCV_TOO_LARGE)
369           assert_perror (err);
370       }
371 }
372
373
374 struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
375 struct mutex _hurd_signal_preempt_lock;
376
377 /* Mask of stop signals.  */
378 #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
379                   sigmask (SIGSTOP) | sigmask (SIGTSTP))
380
381 /* Deliver a signal.
382    SS->lock is held on entry and released before return.  */
383 void
384 _hurd_internal_post_signal (struct hurd_sigstate *ss,
385                             int signo, int sigcode, int sigerror,
386                             mach_port_t reply_port,
387                             mach_msg_type_name_t reply_port_type)
388 {
389   struct machine_thread_all_state thread_state;
390   enum { stop, ignore, core, term, handle } act;
391   sighandler_t handler;
392   struct hurd_signal_preempt *pe;
393   sighandler_t (*preempt) (thread_t, int, int) = NULL;
394   sigset_t pending;
395   int ss_suspended;
396
397   /* Reply to this sig_post message.  */
398   inline void reply ()
399     {
400       post_reply (&reply_port, reply_port_type, 0);
401     }
402
403   /* Wake up a sigsuspend call that is blocking SS->thread.  */
404   inline void sigwakeup (void)
405     {
406       if (ss->suspended != MACH_PORT_NULL)
407         {
408           /* There is a sigsuspend waiting.  Tell it to wake up.  */
409           error_t err;
410           mach_msg_header_t msg;
411           err = __mach_port_insert_right (__mach_task_self (),
412                                           ss->suspended, ss->suspended,
413                                           MACH_MSG_TYPE_MAKE_SEND);
414           assert_perror (err);
415           msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MOVE_SEND, 0);
416           msg.msgh_remote_port = ss->suspended;
417           msg.msgh_local_port = MACH_PORT_NULL;
418           /* These values do not matter.  */
419           msg.msgh_id = 8675309; /* Jenny, Jenny.  */
420           msg.msgh_seqno = 17;  /* Random.  */
421           ss->suspended = MACH_PORT_NULL;
422           err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
423                             MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
424                             MACH_PORT_NULL);
425           assert_perror (err);
426         }
427       __mutex_unlock (&ss->lock);
428     }
429
430  post_signal:
431
432   thread_state.set = 0;         /* We know nothing.  */
433
434   /* Check for a preempted signal.  */
435   __mutex_lock (&_hurd_signal_preempt_lock);
436   for (pe = _hurd_signal_preempt[signo]; pe != NULL; pe = pe->next)
437     if (sigcode >= pe->first && sigcode <= pe->last)
438       {
439         preempt = pe->handler;
440         break;
441       }
442   __mutex_unlock (&_hurd_signal_preempt_lock);
443
444   handler = SIG_DFL;
445   if (preempt)
446     /* Let the preempting handler examine the thread.
447        If it returns SIG_DFL, we run the normal handler;
448        otherwise we use the handler it returns.  */
449     handler = (*preempt) (ss->thread, signo, sigcode);
450
451   ss_suspended = 0;
452
453   if (handler != SIG_DFL)
454     /* Run the preemption-provided handler.  */
455     act = handle;
456   else
457     {
458       /* No preemption.  Do normal handling.  */
459
460       handler = ss->actions[signo].sa_handler;
461
462       if (handler == SIG_DFL)
463         /* Figure out the default action for this signal.  */
464         switch (signo)
465           {
466           case 0:
467             /* A sig_post msg with SIGNO==0 is sent to
468                tell us to check for pending signals.  */
469             act = ignore;
470             break;
471
472           case SIGTTIN:
473           case SIGTTOU:
474           case SIGSTOP:
475           case SIGTSTP:
476             act = stop;
477             break;
478
479           case SIGCONT:
480           case SIGIO:
481           case SIGURG:
482           case SIGCHLD:
483           case SIGWINCH:
484             act = ignore;
485             break;
486
487           case SIGQUIT:
488           case SIGILL:
489           case SIGTRAP:
490           case SIGIOT:
491           case SIGEMT:
492           case SIGFPE:
493           case SIGBUS:
494           case SIGSEGV:
495           case SIGSYS:
496             act = core;
497             break;
498
499           case SIGINFO:
500             if (_hurd_pgrp == _hurd_pid)
501               {
502                 /* We are the process group leader.  Since there is no
503                    user-specified handler for SIGINFO, we use a default one
504                    which prints something interesting.  We use the normal
505                    handler mechanism instead of just doing it here to avoid
506                    the signal thread faulting or blocking in this
507                    potentially hairy operation.  */
508                 act = handle;
509                 handler = _hurd_siginfo_handler;
510               }
511             else
512               act = ignore;
513             break;
514
515           default:
516             act = term;
517             break;
518           }
519       else if (handler == SIG_IGN)
520         act = ignore;
521       else
522         act = handle;
523
524       if (__sigmask (signo) & STOPSIGS)
525         /* Stop signals clear a pending SIGCONT even if they
526            are handled or ignored (but not if preempted).  */
527         ss->pending &= ~sigmask (SIGCONT);
528       else if (signo == SIGCONT)
529         {
530           /* Even if handled or ignored (but not preempted),
531              SIGCONT clears stop signals and resumes the process.  */
532           ss->pending &= ~STOPSIGS;
533           if (_hurd_stopped)
534             {
535               thread_t *threads;
536               unsigned int nthreads, i;
537               error_t err;
538               /* Tell the proc server we are continuing.  */
539               __USEPORT (PROC, __proc_mark_cont (port));
540               /* Fetch ports to all our threads and resume them.  */
541               err = __task_threads (__mach_task_self (), &threads, &nthreads);
542               assert_perror (err);
543               for (i = 0; i < nthreads; ++i)
544                 {
545                   if (threads[i] != _hurd_msgport_thread &&
546                       (act != handle || threads[i] != ss->thread))
547                     __thread_resume (threads[i]);
548                   __mach_port_deallocate (__mach_task_self (), threads[i]);
549                 }
550               __vm_deallocate (__mach_task_self (),
551                                (vm_address_t) threads,
552                                nthreads * sizeof *threads);
553               _hurd_stopped = 0;
554               /* The thread that will run the handler is already suspended.  */
555               ss_suspended = 1;
556             }
557         }
558     }
559
560   if (_hurd_orphaned && act == stop &&
561       (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
562                             __sigmask (SIGTSTP))))
563     {
564       /* If we would ordinarily stop for a job control signal, but we are
565          orphaned so noone would ever notice and continue us again, we just
566          quietly die, alone and in the dark.  */
567       sigcode = signo;
568       signo = SIGKILL;
569       act = term;
570     }
571
572   /* Handle receipt of a blocked signal, or any signal while stopped.
573      It matters that we test ACT first here, because we must never pass
574      SIGNO==0 to __sigismember.  */
575   if ((act != ignore && __sigismember (&ss->blocked, signo)) ||
576       (signo != SIGKILL && _hurd_stopped))
577     {
578       __sigaddset (&ss->pending, signo);
579       /* Save the code to be given to the handler when SIGNO is unblocked.  */
580       ss->pending_data[signo].code = sigcode;
581       ss->pending_data[signo].error = sigerror;
582       act = ignore;
583     }
584
585   /* Perform the chosen action for the signal.  */
586   switch (act)
587     {
588     case stop:
589       if (! _hurd_stopped)
590         {
591           /* Stop all other threads and mark ourselves stopped.  */
592           __USEPORT (PROC,
593                      ({
594                        /* Hold the siglock while stopping other threads to be
595                           sure it is not held by another thread afterwards.  */
596                        __mutex_unlock (&ss->lock);
597                        __mutex_lock (&_hurd_siglock);
598                        __proc_dostop (port, _hurd_msgport_thread);
599                        __mutex_unlock (&_hurd_siglock);
600                        abort_all_rpcs (signo, &thread_state);
601                        __proc_mark_stop (port, signo);
602                      }));
603           _hurd_stopped = 1;
604         }
605
606       __mutex_lock (&ss->lock);
607       sigwakeup ();             /* Wake up sigsuspend.  */
608       break;
609
610     case ignore:
611       /* Nobody cares about this signal.  */
612       break;
613
614     case term:                  /* Time to die.  */
615     case core:                  /* And leave a rotting corpse.  */
616     nirvana:
617       __mutex_unlock (&ss->lock);
618       /* Have the proc server stop all other threads in our task.  */
619       __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
620       /* No more user instructions will be executed.
621          The signal can now be considered delivered.  */
622       reply ();
623       /* Abort all server operations now in progress.  */
624       abort_all_rpcs (signo, &thread_state);
625
626       {
627         int status = W_EXITCODE (0, signo);
628         /* Do a core dump if desired.  Only set the wait status bit saying we
629            in fact dumped core if the operation was actually successful.  */
630         if (act == core && write_corefile (signo, sigcode, sigerror))
631           status |= WCOREFLAG;
632         /* Tell proc how we died and then stick the saber in the gut.  */
633         _hurd_exit (status);
634         /* NOTREACHED */
635       }
636
637     case handle:
638       /* Call a handler for this signal.  */
639       {
640         struct sigcontext *scp;
641         int wait_for_reply;
642
643         /* Stop the thread and abort its pending RPC operations.  */
644         if (! ss_suspended)
645           __thread_suspend (ss->thread);
646         wait_for_reply = (abort_rpcs (ss, signo, &thread_state,
647                                       &reply_port, reply_port_type)
648                           != MACH_PORT_NULL);
649
650         /* Call the machine-dependent function to set the thread up
651            to run the signal handler, and preserve its old context.  */
652         scp = _hurd_setup_sighandler (ss, handler,
653                                       signo, sigcode,
654                                       wait_for_reply, &thread_state);
655         if (scp == NULL)
656           {
657             /* We got a fault setting up the stack frame for the handler.
658                Nothing to do but die; BSD gets SIGILL in this case.  */
659             sigcode = signo;    /* XXX ? */
660             signo = SIGILL;
661             act = core;
662             goto nirvana;
663           }
664
665         /* Set the machine-independent parts of the signal context.  */
666
667         scp->sc_error = sigerror;
668         {
669           /* Fetch the thread variable for the MiG reply port,
670              and set it to MACH_PORT_NULL.  */
671           mach_port_t *loc = interrupted_reply_port_location (&thread_state);
672           if (loc)
673             {
674               scp->sc_reply_port = *loc;
675               *loc = MACH_PORT_NULL;
676             }
677           else
678             scp->sc_reply_port = MACH_PORT_NULL;
679         }
680
681         /* Block SIGNO and requested signals while running the handler.  */
682         scp->sc_mask = ss->blocked;
683         ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
684
685         /* Save the intr_port in use by the interrupted code,
686            and clear the cell before running the trampoline.  */
687         scp->sc_intr_port = ss->intr_port;
688         ss->intr_port = MACH_PORT_NULL;
689
690         /* Start the thread running the handler (or possibly waiting for an
691            RPC reply before running the handler).  */
692         __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
693                             (int *) &thread_state.basic,
694                             MACHINE_THREAD_STATE_COUNT);
695         __thread_resume (ss->thread);
696         thread_state.set = 0;   /* Everything we know is now wrong.  */
697         break;
698       }
699     }
700
701   /* The signal has either been ignored or is now being handled.  We can
702      consider it delivered and reply to the killer.  The exception is
703      signal 0, which can be sent by a user thread to make us check for
704      pending signals.  In that case we want to deliver the pending signals
705      before replying.  */
706   if (signo != 0)
707     reply ();
708
709   /* We get here only if we are handling or ignoring the signal;
710      otherwise we are stopped or dead by now.  We still hold SS->lock.
711      Check for pending signals, and loop to post them.  */
712 #define PENDING (!_hurd_stopped && (pending = ss->pending & ~ss->blocked))
713   if (PENDING)
714     {
715     pending:
716       for (signo = 1; signo < NSIG; ++signo)
717         if (__sigismember (&pending, signo))
718           {
719             __sigdelset (&ss->pending, signo);
720             sigcode = ss->pending_data[signo].code;
721             sigerror = ss->pending_data[signo].error;
722             goto post_signal;
723           }
724     }
725
726   /* No more signals pending; SS->lock is still locked.  */
727   sigwakeup ();
728
729   /* No pending signals left undelivered for this thread.
730      If we were sent signal 0, we need to check for pending
731      signals for all threads.  */
732   if (signo == 0)
733     {
734       __mutex_lock (&_hurd_siglock);
735       for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
736         {
737           __mutex_lock (&ss->lock);
738           if (PENDING)
739             goto pending;
740           __mutex_unlock (&ss->lock);
741         }
742       __mutex_unlock (&_hurd_siglock);
743     }
744
745   /* All pending signals delivered to all threads.
746      Now we can send the reply message even for signal 0.  */
747   reply ();
748 }
749
750 /* Implement the sig_post RPC from <hurd/msg.defs>;
751    sent when someone wants us to get a signal.  */
752 kern_return_t
753 _S_sig_post (mach_port_t me,
754              mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
755              int signo,
756              mach_port_t refport)
757 {
758   struct hurd_sigstate *ss;
759
760   if (signo < 0 || signo >= NSIG)
761     return EINVAL;
762
763   if (refport == __mach_task_self ())
764     /* Can send any signal.  */
765     goto win;
766
767   /* Avoid needing to check for this below.  */
768   if (refport == MACH_PORT_NULL)
769     return EPERM;
770
771   switch (signo)
772     {
773     case SIGINT:
774     case SIGQUIT:
775     case SIGTSTP:
776     case SIGHUP:
777     case SIGINFO:
778     case SIGTTIN:
779     case SIGTTOU:
780       /* Job control signals can be sent by the controlling terminal.  */
781       if (__USEPORT (CTTYID, port == refport))
782         goto win;
783       break;
784
785     case SIGCONT:
786       {
787         /* A continue signal can be sent by anyone in the session.  */
788         mach_port_t sessport;
789         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
790           { 
791             __mach_port_deallocate (__mach_task_self (), sessport);
792             if (refport == sessport)
793               goto win;
794           }
795       }
796       break;
797
798     case SIGIO:
799     case SIGURG:
800       {
801         /* Any io object a file descriptor refers to might send us
802            one of these signals using its async ID port for REFPORT.
803
804            This is pretty wide open; it is not unlikely that some random
805            process can at least open for reading something we have open,
806            get its async ID port, and send us a spurious SIGIO or SIGURG
807            signal.  But BSD is actually wider open than that!--you can set
808            the owner of an io object to any process or process group
809            whatsoever and send them gratuitous signals.
810
811            Someday we could implement some reasonable scheme for
812            authorizing SIGIO and SIGURG signals properly.  */
813
814         int d;
815         __mutex_lock (&_hurd_dtable_lock);
816         for (d = 0; (unsigned int) d < (unsigned int) _hurd_dtablesize; ++d)
817           {
818             struct hurd_userlink ulink;
819             io_t port;
820             mach_port_t asyncid;
821             if (_hurd_dtable[d] == NULL)
822               continue;
823             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
824             if (! __io_get_icky_async_id (port, &asyncid))
825               {
826                 if (refport == asyncid)
827                   /* Break out of the loop on the next iteration.  */
828                   d = -1;
829                 __mach_port_deallocate (__mach_task_self (), asyncid);
830               }
831             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
832           }
833         /* If we found a lucky winner, we've set D to -1 in the loop.  */
834         if (d < 0)
835           goto win;
836       }
837     }
838
839   /* If this signal is legit, we have done `goto win' by now.
840      When we return the error, mig deallocates REFPORT.  */
841   return EPERM;
842
843  win:
844   /* Deallocate the REFPORT send right; we are done with it.  */
845   __mach_port_deallocate (__mach_task_self (), refport);
846
847   /* Get a hold of the designated signal-receiving thread.  */
848   ss = _hurd_thread_sigstate (_hurd_sigthread);
849
850   /* Post the signal; this will reply when the signal can be considered
851      delivered.  */
852   _hurd_internal_post_signal (ss, signo, 0, 0, reply_port, reply_port_type);
853
854   return MIG_NO_REPLY;          /* Already replied.  */
855 }
856 \f
857 extern void __mig_init (void *);
858
859 #include <mach/task_special_ports.h>
860
861 /* Initialize the message port and _hurd_sigthread and start the signal
862    thread.  */
863
864 void
865 _hurdsig_init (void)
866 {
867   error_t err;
868   vm_size_t stacksize;
869
870   __mutex_init (&_hurd_siglock);
871
872   if (err = __mach_port_allocate (__mach_task_self (),
873                                   MACH_PORT_RIGHT_RECEIVE,
874                                   &_hurd_msgport))
875     __libc_fatal ("hurd: Can't create message port receive right\n");
876   
877   /* Make a send right to the signal port.  */
878   if (err = __mach_port_insert_right (__mach_task_self (),
879                                       _hurd_msgport,
880                                       _hurd_msgport,
881                                       MACH_MSG_TYPE_MAKE_SEND))
882     __libc_fatal ("hurd: Can't create send right to message port\n");
883
884   /* Set the default thread to receive task-global signals
885      to this one, the main (first) user thread.  */
886   _hurd_sigthread = __mach_thread_self ();
887
888   /* Start the signal thread listening on the message port.  */
889
890   if (err = __thread_create (__mach_task_self (), &_hurd_msgport_thread))
891     __libc_fatal ("hurd: Can't create signal thread\n");
892
893   stacksize = __vm_page_size * 4; /* Small stack for signal thread.  */
894   if (err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
895                                  _hurd_msgport_receive,
896                                  (vm_address_t *) &__hurd_sigthread_stack_base,
897                                  &stacksize))
898     __libc_fatal ("hurd: Can't setup signal thread\n");
899
900   __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
901   __hurd_sigthread_variables =
902     malloc (__hurd_threadvar_max * sizeof (unsigned long int));
903   if (__hurd_sigthread_variables == NULL)
904     __libc_fatal ("hurd: Can't allocate thread variables for signal thread\n");
905
906   /* Reinitialize the MiG support routines so they will use a per-thread
907      variable for the cached reply port.  */
908   __mig_init ((void *) __hurd_sigthread_stack_base);
909
910   if (err = __thread_resume (_hurd_msgport_thread))
911     __libc_fatal ("hurd: Can't resume signal thread\n");
912     
913 #if 0                           /* Don't confuse poor gdb.  */
914   /* Receive exceptions on the signal port.  */
915   __task_set_special_port (__mach_task_self (),
916                            TASK_EXCEPTION_PORT, _hurd_msgport);
917 #endif
918 }
919 \f                               /* XXXX */
920 /* Reauthenticate with the proc server.  */
921
922 static void
923 reauth_proc (mach_port_t new)
924 {
925   mach_port_t ref, ignore;
926
927   ref = __mach_reply_port ();
928   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
929                        __proc_reauthenticate (port, ref,
930                                               MACH_MSG_TYPE_MAKE_SEND) ||
931                        __auth_user_authenticate (new, port, ref,
932                                                  MACH_MSG_TYPE_MAKE_SEND,
933                                                  &ignore))
934       && ignore != MACH_PORT_NULL)
935     __mach_port_deallocate (__mach_task_self (), ignore);
936   __mach_port_destroy (__mach_task_self (), ref);
937
938   (void) &reauth_proc;          /* Silence compiler warning.  */
939 }
940 text_set_element (__hurd_reauth_hook, reauth_proc);
941 \f
942 /* Like `getenv', but safe for the signal thread to run.
943    If the environment is trashed, this will just return NULL.  */
944
945 const char *
946 _hurdsig_getenv (const char *variable)
947 {
948   if (_hurdsig_catch_fault (SIGSEGV))
949     /* We bombed in getenv.  */
950     return NULL;
951   else
952     {
953       const char *value = getenv (variable);
954       /* Fault now if VALUE is a bogus string.  */
955       (void) strlen (value);
956       _hurdsig_end_catch_fault ();
957       return value;
958     }
959 }