initial import
[platform/upstream/glibc.git] / hurd / hurdsig.c
1 /* Copyright (C) 1991, 1992, 1993, 1994, 1995 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 <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 */
27
28 const char *_hurdsig_getenv (const char *);
29
30 struct mutex _hurd_siglock;
31 int _hurd_stopped;
32
33 /* Port that receives signals and other miscellaneous messages.  */
34 mach_port_t _hurd_msgport;
35
36 /* Thread listening on it.  */
37 thread_t _hurd_msgport_thread;
38
39 /* Thread which receives task-global signals.  */
40 thread_t _hurd_sigthread;
41
42 /* Linked-list of per-thread signal state.  */
43 struct hurd_sigstate *_hurd_sigstates;
44 \f
45 static void
46 default_sigaction (struct sigaction actions[NSIG])
47 {
48   int signo;
49
50   __sigemptyset (&actions[0].sa_mask);
51   actions[0].sa_flags = SA_RESTART;
52   actions[0].sa_handler = SIG_DFL;
53
54   for (signo = 1; signo < NSIG; ++signo)
55     actions[signo] = actions[0];
56 }
57
58 struct hurd_sigstate *
59 _hurd_thread_sigstate (thread_t thread)
60 {
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)
67     {
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);
73
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;
84
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
90         {
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)
96             {
97               __spin_lock (&s->lock);
98               memcpy (ss->actions, s->actions, sizeof (s->actions));
99               __spin_unlock (&s->lock);
100             }
101           else
102             default_sigaction (ss->actions);
103         }
104
105       ss->next = _hurd_sigstates;
106       _hurd_sigstates = ss;
107     }
108   __mutex_unlock (&_hurd_siglock);
109   return ss;
110 }
111 \f
112 /* Signal delivery itself is on this page.  */
113
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>
125
126 int _hurd_core_limit;   /* XXX */
127
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)
132 {
133   error_t err;
134   mach_port_t coreserver;
135   file_t file, coredir;
136   const char *name;
137
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.  */
142
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;
152
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;
165
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;
179 }
180
181
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)
187 {
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;
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               int untraced)
208 {
209   if (!(state->set & THREAD_ABORTED))
210     {
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;
215     }
216
217   if (reply_port)
218     post_reply (reply_port, reply_port_type, untraced, 0);
219
220   machine_get_basic_state (ss->thread, state);
221 }
222
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.  */
226
227 static mach_port_t *
228 interrupted_reply_port_location (struct machine_thread_all_state *thread_state)
229 {
230   mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
231     (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
232
233   if (_hurdsig_catch_fault (SIGSEGV))
234     {
235       assert (_hurdsig_fault_sigcode == (long int) portloc);
236       /* Faulted trying to read the stack.  */
237       return NULL;
238     }
239
240   /* Fault now if this pointer is bogus.  */
241   *(volatile mach_port_t *) portloc = *portloc;
242
243   _hurdsig_end_catch_fault ();
244
245   return portloc;
246 }
247
248
249 /* SS->thread is suspended.
250
251    Abort any interruptible RPC operation the thread is doing.
252
253    This uses only the constant member SS->thread and the unlocked, atomically
254    set member SS->intr_port, so no locking is needed.
255
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.
260
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.  */
263
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)
269 {
270   mach_port_t msging_port;
271   mach_port_t intr_port;
272
273   *state_change = 0;
274
275   intr_port = ss->intr_port;
276   if (intr_port == MACH_PORT_NULL)
277     /* No interruption needs done.  */
278     return MACH_PORT_NULL;
279
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);
283
284   if (_hurdsig_rcv_interrupted_p (state, &msging_port))
285     {
286       error_t err;
287
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.  */
296
297       err = __interrupt_operation (intr_port);
298
299       if (err)
300         {
301           mach_port_t *reply;
302
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);
306
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;
315
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;
322         }
323
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;
330
331       return err ? MACH_PORT_NULL : msging_port;
332     }
333
334   /* One of the following is true:
335
336      1. The RPC has not yet been sent.  The thread will start its operation
337      after the signal has been handled.
338
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.
341
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).  */
345
346   return MACH_PORT_NULL;
347 }
348
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.  */
354
355 static void
356 abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
357 {
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.  */
361
362   struct hurd_sigstate *ss;
363   size_t nthreads;
364   mach_port_t *reply_ports;
365
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;
371
372   reply_ports = alloca (nthreads * sizeof *reply_ports);
373
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
379       {
380         int state_changed;
381         state->set = 0;         /* Reset scratch area.  */
382
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);
394       }
395
396   /* Wait for replies from all the successfully interrupted RPCs.  */
397   while (nthreads-- > 0)
398     if (reply_ports[nthreads] != MACH_PORT_NULL)
399       {
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);
407       }
408 }
409
410
411 struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
412 struct mutex _hurd_signal_preempt_lock;
413
414 /* Mask of stop signals.  */
415 #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
416                   sigmask (SIGSTOP) | sigmask (SIGTSTP))
417
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)
425 {
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;
433
434   /* Reply to this sig_post message.  */
435   inline void reply (void)
436     {
437       post_reply (&reply_port, reply_port_type, untraced, 0);
438     }
439
440   /* Mark the signal as pending.  */
441   void mark_pending (void)
442     {
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;
448     }
449
450   /* Suspend the process with SIGNO.  */
451   void suspend (void)
452     {
453       /* Stop all other threads and mark ourselves stopped.  */
454       __USEPORT (PROC,
455                  ({
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;
465     }
466
467  post_signal:
468
469   thread_state.set = 0;         /* We know nothing.  */
470
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)
476       {
477         preempt = pe->handler;
478         break;
479       }
480   __mutex_unlock (&_hurd_signal_preempt_lock);
481
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);
488
489   ss_suspended = 0;
490
491   if (handler != SIG_DFL)
492     /* Run the preemption-provided handler.  */
493     act = handle;
494   else
495     {
496       /* No preemption.  Do normal handling.  */
497
498       __spin_lock (&ss->lock);
499
500       handler = ss->actions[signo].sa_handler;
501
502       if (!untraced && (_hurd_exec_flags & EXEC_TRACED))
503         {
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;
514         }
515
516       if (handler == SIG_DFL)
517         /* Figure out the default action for this signal.  */
518         switch (signo)
519           {
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;
525
526           case SIGTTIN:
527           case SIGTTOU:
528           case SIGSTOP:
529           case SIGTSTP:
530             act = stop;
531             break;
532
533           case SIGCONT:
534           case SIGIO:
535           case SIGURG:
536           case SIGCHLD:
537           case SIGWINCH:
538             act = ignore;
539             break;
540
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;
552
553           case SIGINFO:
554             if (_hurd_pgrp == _hurd_pid)
555               {
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;
564               }
565             else
566               act = ignore;
567             break;
568
569           default:
570             act = term;
571             break;
572           }
573       else if (handler == SIG_IGN)
574         act = ignore;
575       else
576         act = handle;
577
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
583         {
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;
588
589           if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
590             {
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)
601                 {
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]);
606                 }
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;
613             }
614         }
615     }
616
617   if (_hurd_orphaned && act == stop &&
618       (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
619                             __sigmask (SIGTSTP))))
620     {
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;
627     }
628
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))
634     {
635       mark_pending ();
636       act = ignore;
637     }
638
639   /* Perform the chosen action for the signal.  */
640   switch (act)
641     {
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;
652
653     case ignore:
654       /* Nobody cares about this signal.  */
655       break;
656
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);
667
668       {
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 */
677       }
678
679     case handle:
680       /* Call a handler for this signal.  */
681       {
682         struct sigcontext *scp;
683         int wait_for_reply, state_changed;
684
685         /* Stop the thread and abort its pending RPC operations.  */
686         if (! ss_suspended)
687           __thread_suspend (ss->thread);
688
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);
695
696         wait_for_reply = (abort_rpcs (ss, signo, &thread_state, &state_changed,
697                                       &reply_port, reply_port_type, untraced)
698                           != MACH_PORT_NULL);
699
700         if (ss->critical_section)
701           {
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;
709           }
710
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)
717           {
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;
724           }
725
726         /* Set the machine-independent parts of the signal context.  */
727
728         scp->sc_error = sigerror;
729         {
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)
734             {
735               scp->sc_reply_port = *loc;
736               *loc = MACH_PORT_NULL;
737             }
738           else
739             scp->sc_reply_port = MACH_PORT_NULL;
740         }
741
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;
745
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;
750
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;
759       }
760     }
761
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 ();
769
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)
774     {
775     pending:
776       for (signo = 1; signo < NSIG; ++signo)
777         if (__sigismember (&pending, signo))
778           {
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;
784           }
785     }
786
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)
791     {
792       __spin_unlock (&ss->lock);
793       __mutex_lock (&_hurd_siglock);
794       for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
795         {
796           __spin_lock (&ss->lock);
797           if (PENDING)
798             goto pending;
799           __spin_unlock (&ss->lock);
800         }
801       __mutex_unlock (&_hurd_siglock);
802     }
803   else
804     {
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)
808         {
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);
827         }
828       __spin_unlock (&ss->lock);
829     }
830
831   /* All pending signals delivered to all threads.
832      Now we can send the reply message even for signal 0.  */
833   reply ();
834 }
835 \f
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.  */
838
839 static error_t
840 signal_allowed (int signo, mach_port_t refport)
841 {
842   if (signo < 0 || signo >= NSIG)
843     return EINVAL;
844
845   if (refport == __mach_task_self ())
846     /* Can send any signal.  */
847     goto win;
848
849   /* Avoid needing to check for this below.  */
850   if (refport == MACH_PORT_NULL)
851     return EPERM;
852
853   switch (signo)
854     {
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;
866
867     case SIGCONT:
868       {
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)))
872           { 
873             __mach_port_deallocate (__mach_task_self (), sessport);
874             if (refport == sessport)
875               goto win;
876           }
877       }
878       break;
879
880     case SIGIO:
881     case SIGURG:
882       {
883         /* Any io object a file descriptor refers to might send us
884            one of these signals using its async ID port for REFPORT.
885
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.
892
893            Someday we could implement some reasonable scheme for
894            authorizing SIGIO and SIGURG signals properly.  */
895
896         int d;
897         __mutex_lock (&_hurd_dtable_lock);
898         for (d = 0; (unsigned int) d < (unsigned int) _hurd_dtablesize; ++d)
899           {
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))
907               {
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);
912               }
913             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
914           }
915         /* If we found a lucky winner, we've set D to -1 in the loop.  */
916         if (d < 0)
917           goto win;
918       }
919     }
920
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;
924
925  win:
926   /* Deallocate the REFPORT send right; we are done with it.  */
927   __mach_port_deallocate (__mach_task_self (), refport);
928
929   return 0;
930 }
931
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)
939 {
940   error_t err;
941
942   if (err = signal_allowed (signo, refport))
943     return err;
944
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.  */
950
951   return MIG_NO_REPLY;          /* Already replied.  */
952 }
953
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)
963 {
964   error_t err;
965
966   if (err = signal_allowed (signo, refport))
967     return err;
968
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. */
974
975   return MIG_NO_REPLY;          /* Already replied.  */
976 }
977 \f
978 extern void __mig_init (void *);
979
980 #include <mach/task_special_ports.h>
981
982 /* Initialize the message port and _hurd_sigthread and start the signal
983    thread.  */
984
985 void
986 _hurdsig_init (void)
987 {
988   error_t err;
989   vm_size_t stacksize;
990
991   __mutex_init (&_hurd_siglock);
992
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");
997   
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");
1004
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 ();
1008
1009   /* Start the signal thread listening on the message port.  */
1010
1011   if (err = __thread_create (__mach_task_self (), &_hurd_msgport_thread))
1012     __libc_fatal ("hurd: Can't create signal thread\n");
1013
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");
1020
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");
1026
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);
1030
1031   if (err = __thread_resume (_hurd_msgport_thread))
1032     __libc_fatal ("hurd: Can't resume signal thread\n");
1033     
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
1039 }
1040 \f                               /* XXXX */
1041 /* Reauthenticate with the proc server.  */
1042
1043 static void
1044 reauth_proc (mach_port_t new)
1045 {
1046   mach_port_t ref, ignore;
1047
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);
1058
1059   (void) &reauth_proc;          /* Silence compiler warning.  */
1060 }
1061 text_set_element (_hurd_reauth_hook, reauth_proc);
1062 \f
1063 /* Like `getenv', but safe for the signal thread to run.
1064    If the environment is trashed, this will just return NULL.  */
1065
1066 const char *
1067 _hurdsig_getenv (const char *variable)
1068 {
1069   if (_hurdsig_catch_fault (SIGSEGV))
1070     /* We bombed in getenv.  */
1071     return NULL;
1072   else
1073     {
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;
1079     }
1080 }