Fri May 26 13:00:08 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
[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   error_t err;
189   if (reply_port == NULL || *reply_port == MACH_PORT_NULL)
190     return;
191   err = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply)
192     (*reply_port, reply_port_type, result);
193   *reply_port = MACH_PORT_NULL;
194   if (err != MACH_SEND_INVALID_DEST) /* Ignore dead reply port.  */
195     assert_perror (err);
196 }
197
198
199 /* The lowest-numbered thread state flavor value is 1,
200    so we use bit 0 in machine_thread_all_state.set to
201    record whether we have done thread_abort.  */
202 #define THREAD_ABORTED 1
203
204 /* SS->thread is suspended.  Abort the thread and get its basic state.  If
205    REPLY_PORT is not NULL, send a reply on *REPLY_PORT after aborting the
206    thread.  */
207 static void
208 abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
209               mach_port_t *reply_port, mach_msg_type_name_t reply_port_type,
210               int untraced)
211 {
212   if (!(state->set & THREAD_ABORTED))
213     {
214       error_t err = __thread_abort (ss->thread);
215       assert_perror (err);
216       /* Clear all thread state flavor set bits, because thread_abort may
217          have changed the state.  */
218       state->set = THREAD_ABORTED;
219     }
220
221   if (reply_port)
222     post_reply (reply_port, reply_port_type, untraced, 0);
223
224   machine_get_basic_state (ss->thread, state);
225 }
226
227 /* Find the location of the MiG reply port cell in use by the thread whose
228    state is described by THREAD_STATE.  Make sure that this location can be
229    set without faulting, or else return NULL.  */
230
231 static mach_port_t *
232 interrupted_reply_port_location (struct machine_thread_all_state *thread_state)
233 {
234   mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
235     (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
236
237   if (_hurdsig_catch_fault (SIGSEGV))
238     {
239       assert (_hurdsig_fault_sigcode == (long int) portloc);
240       /* Faulted trying to read the stack.  */
241       return NULL;
242     }
243
244   /* Fault now if this pointer is bogus.  */
245   *(volatile mach_port_t *) portloc = *portloc;
246
247   _hurdsig_end_catch_fault ();
248
249   return portloc;
250 }
251
252
253 /* SS->thread is suspended.
254
255    Abort any interruptible RPC operation the thread is doing.
256
257    This uses only the constant member SS->thread and the unlocked, atomically
258    set member SS->intr_port, so no locking is needed.
259
260    If successfully sent an interrupt_operation and therefore the thread should
261    wait for its pending RPC to return (possibly EINTR) before taking the
262    incoming signal, returns the reply port to be received on.  Otherwise
263    returns MACH_PORT_NULL.
264
265    *STATE_CHANGE is set nonzero if STATE->basic was modified and should
266    be applied back to the thread if it might ever run again, else zero.  */
267
268 static mach_port_t
269 abort_rpcs (struct hurd_sigstate *ss, int signo,
270             struct machine_thread_all_state *state, int *state_change,
271             mach_port_t *reply_port, mach_msg_type_name_t reply_port_type,
272             int untraced)
273 {
274   mach_port_t msging_port;
275   mach_port_t intr_port;
276
277   *state_change = 0;
278
279   intr_port = ss->intr_port;
280   if (intr_port == MACH_PORT_NULL)
281     /* No interruption needs done.  */
282     return MACH_PORT_NULL;
283
284   /* Abort the thread's kernel context, so any pending message send or
285      receive completes immediately or aborts.  */
286   abort_thread (ss, state, reply_port, reply_port_type, untraced);
287
288   if (_hurdsig_rcv_interrupted_p (state, &msging_port))
289     {
290       error_t err;
291
292       /* The RPC request message was sent and the thread was waiting for
293          the reply message; now the message receive has been aborted, so
294          the mach_msg_call will return MACH_RCV_INTERRUPTED.  We must tell
295          the server to interrupt the pending operation.  The thread must
296          wait for the reply message before running the signal handler (to
297          guarantee that the operation has finished being interrupted), so
298          our nonzero return tells the trampoline code to finish the message
299          receive operation before running the handler.  */
300
301       err = __interrupt_operation (intr_port);
302
303       if (err)
304         {
305           mach_port_t *reply;
306
307           /* The interrupt didn't work.
308              Destroy the receive right the thread is blocked on.  */
309           __mach_port_destroy (__mach_task_self (), msging_port);
310
311           /* The system call return value register now contains
312              MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
313              call.  Since we have just destroyed the receive right, the
314              retry will fail with MACH_RCV_INVALID_NAME.  Instead, just
315              change the return value here to EINTR so mach_msg will not
316              retry and the EINTR error code will propagate up.  */
317           state->basic.SYSRETURN = EINTR;
318           *state_change = 1;
319
320           /* If that was the thread's MiG reply port (which I think should
321              always be the case), clear the reply port cell so it won't be
322              reused.  */
323           reply = interrupted_reply_port_location (state);
324           if (reply != NULL && *reply == msging_port)
325             *reply = MACH_PORT_NULL;
326         }
327
328       /* All threads whose RPCs were interrupted by the interrupt_operation
329          call above will retry their RPCs unless we clear SS->intr_port.
330          So we clear it for the thread taking a signal when SA_RESTART is
331          clear, so that its call returns EINTR.  */
332       if (!(ss->actions[signo].sa_flags & SA_RESTART))
333         ss->intr_port = MACH_PORT_NULL;
334
335       return err ? MACH_PORT_NULL : msging_port;
336     }
337
338   /* One of the following is true:
339
340      1. The RPC has not yet been sent.  The thread will start its operation
341      after the signal has been handled.
342
343      2. The RPC has finished, but not yet cleared SS->intr_port.
344      The thread will clear SS->intr_port after running the handler.
345
346      3. The RPC request message was being sent was aborted.  The mach_msg
347      system call will return MACH_SEND_INTERRUPTED, and HURD_EINTR_RPC will
348      notice the interruption (either retrying the RPC or returning EINTR).  */
349
350   return MACH_PORT_NULL;
351 }
352
353 /* Abort the RPCs being run by all threads but this one;
354    all other threads should be suspended.  If LIVE is nonzero, those
355    threads may run again, so they should be adjusted as necessary to be
356    happy when resumed.  STATE is clobbered as a scratch area; its initial
357    contents are ignored, and its contents on return are not useful.  */
358
359 static void
360 abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
361 {
362   /* We can just loop over the sigstates.  Any thread doing something
363      interruptible must have one.  We needn't bother locking because all
364      other threads are stopped.  */
365
366   struct hurd_sigstate *ss;
367   size_t nthreads;
368   mach_port_t *reply_ports;
369
370   /* First loop over the sigstates to count them.
371      We need to know how big a vector we will need for REPLY_PORTS.  */
372   nthreads = 0;
373   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
374     ++nthreads;
375
376   reply_ports = alloca (nthreads * sizeof *reply_ports);
377
378   nthreads = 0;
379   for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
380     if (ss->thread == _hurd_msgport_thread)
381       reply_ports[nthreads++] = MACH_PORT_NULL;
382     else
383       {
384         int state_changed;
385         state->set = 0;         /* Reset scratch area.  */
386
387         /* Abort any operation in progress with interrupt_operation.
388            Record the reply port the thread is waiting on.
389            We will wait for all the replies below.  */
390         reply_ports[nthreads++] = abort_rpcs (ss, signo, state, &state_changed,
391                                               NULL, 0, 0);
392         if (state_changed && live)
393           /* Aborting the RPC needed to change this thread's state,
394              and it might ever run again.  So write back its state.  */
395           __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
396                               (natural_t *) &state->basic,
397                               MACHINE_THREAD_STATE_COUNT);
398       }
399
400   /* Wait for replies from all the successfully interrupted RPCs.  */
401   while (nthreads-- > 0)
402     if (reply_ports[nthreads] != MACH_PORT_NULL)
403       {
404         error_t err;
405         mach_msg_header_t head;
406         err = __mach_msg (&head, MACH_RCV_MSG, 0, sizeof head,
407                           reply_ports[nthreads],
408                           MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
409         if (err != MACH_RCV_TOO_LARGE)
410           assert_perror (err);
411       }
412 }
413
414
415 struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
416 struct mutex _hurd_signal_preempt_lock;
417
418 /* Mask of stop signals.  */
419 #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
420                   sigmask (SIGSTOP) | sigmask (SIGTSTP))
421
422 /* Deliver a signal.  SS is not locked.  */
423 void
424 _hurd_internal_post_signal (struct hurd_sigstate *ss,
425                             int signo, long int sigcode, int sigerror,
426                             mach_port_t reply_port,
427                             mach_msg_type_name_t reply_port_type,
428                             int untraced)
429 {
430   error_t err;
431   struct machine_thread_all_state thread_state;
432   enum { stop, ignore, core, term, handle } act;
433   sighandler_t handler;
434   struct hurd_signal_preempt *pe;
435   sighandler_t (*preempt) (thread_t, int, long int, int) = NULL;
436   sigset_t pending;
437   int ss_suspended;
438
439   /* Reply to this sig_post message.  */
440   inline void reply (void)
441     {
442       post_reply (&reply_port, reply_port_type, untraced, 0);
443     }
444
445   /* Mark the signal as pending.  */
446   void mark_pending (void)
447     {
448       __sigaddset (&ss->pending, signo);
449       /* Save the code to be given to the handler when SIGNO is
450          unblocked.  */
451       ss->pending_data[signo].code = sigcode;
452       ss->pending_data[signo].error = sigerror;
453     }
454
455   /* Suspend the process with SIGNO.  */
456   void suspend (void)
457     {
458       /* Stop all other threads and mark ourselves stopped.  */
459       __USEPORT (PROC,
460                  ({
461                    /* Hold the siglock while stopping other threads to be
462                       sure it is not held by another thread afterwards.  */
463                    __mutex_lock (&_hurd_siglock);
464                    __proc_dostop (port, _hurd_msgport_thread);
465                    __mutex_unlock (&_hurd_siglock);
466                    abort_all_rpcs (signo, &thread_state, 1);
467                    __proc_mark_stop (port, signo);
468                  }));
469       _hurd_stopped = 1;
470     }
471
472  post_signal:
473
474   thread_state.set = 0;         /* We know nothing.  */
475
476   /* Check for a preempted signal.  Preempted signals
477      can arrive during critical sections.  */
478   __mutex_lock (&_hurd_signal_preempt_lock);
479   for (pe = _hurd_signal_preempt[signo]; pe != NULL; pe = pe->next)
480     if (pe->handler && sigcode >= pe->first && sigcode <= pe->last)
481       {
482         preempt = pe->handler;
483         break;
484       }
485   __mutex_unlock (&_hurd_signal_preempt_lock);
486
487   handler = SIG_DFL;
488   if (preempt)
489     /* Let the preempting handler examine the thread.
490        If it returns SIG_DFL, we run the normal handler;
491        otherwise we use the handler it returns.  */
492     handler = (*preempt) (ss->thread, signo, sigcode, sigerror);
493
494   ss_suspended = 0;
495
496   if (handler != SIG_DFL)
497     /* Run the preemption-provided handler.  */
498     act = handle;
499   else
500     {
501       /* No preemption.  Do normal handling.  */
502
503       __spin_lock (&ss->lock);
504
505       handler = ss->actions[signo].sa_handler;
506
507       if (!untraced && (_hurd_exec_flags & EXEC_TRACED))
508         {
509           /* We are being traced.  Stop to tell the debugger of the signal.  */
510           if (_hurd_stopped)
511             /* Already stopped.  Mark the signal as pending;
512                when resumed, we will notice it and stop again.  */
513             mark_pending ();
514           else
515             suspend ();
516           __spin_unlock (&ss->lock);
517           reply ();
518           return;
519         }
520
521       if (handler == SIG_DFL)
522         /* Figure out the default action for this signal.  */
523         switch (signo)
524           {
525           case 0:
526             /* A sig_post msg with SIGNO==0 is sent to
527                tell us to check for pending signals.  */
528             act = ignore;
529             break;
530
531           case SIGTTIN:
532           case SIGTTOU:
533           case SIGSTOP:
534           case SIGTSTP:
535             act = stop;
536             break;
537
538           case SIGCONT:
539           case SIGIO:
540           case SIGURG:
541           case SIGCHLD:
542           case SIGWINCH:
543             act = ignore;
544             break;
545
546           case SIGQUIT:
547           case SIGILL:
548           case SIGTRAP:
549           case SIGIOT:
550           case SIGEMT:
551           case SIGFPE:
552           case SIGBUS:
553           case SIGSEGV:
554           case SIGSYS:
555             act = core;
556             break;
557
558           case SIGINFO:
559             if (_hurd_pgrp == _hurd_pid)
560               {
561                 /* We are the process group leader.  Since there is no
562                    user-specified handler for SIGINFO, we use a default one
563                    which prints something interesting.  We use the normal
564                    handler mechanism instead of just doing it here to avoid
565                    the signal thread faulting or blocking in this
566                    potentially hairy operation.  */
567                 act = handle;
568                 handler = _hurd_siginfo_handler;
569               }
570             else
571               act = ignore;
572             break;
573
574           default:
575             act = term;
576             break;
577           }
578       else if (handler == SIG_IGN)
579         act = ignore;
580       else
581         act = handle;
582
583       if (__sigmask (signo) & STOPSIGS)
584         /* Stop signals clear a pending SIGCONT even if they
585            are handled or ignored (but not if preempted).  */
586         ss->pending &= ~sigmask (SIGCONT);
587       else
588         {
589           if (signo == SIGCONT)
590             /* Even if handled or ignored (but not preempted), SIGCONT clears
591                stop signals and resumes the process.  */
592             ss->pending &= ~STOPSIGS;
593
594           if (_hurd_stopped && act != stop && (untraced || signo == SIGCONT))
595             {
596               /* Resume the process from being stopped.  */
597               thread_t *threads;
598               mach_msg_type_number_t nthreads, i;
599               error_t err;
600               /* Tell the proc server we are continuing.  */
601               __USEPORT (PROC, __proc_mark_cont (port));
602               /* Fetch ports to all our threads and resume them.  */
603               err = __task_threads (__mach_task_self (), &threads, &nthreads);
604               assert_perror (err);
605               for (i = 0; i < nthreads; ++i)
606                 {
607                   if (threads[i] != _hurd_msgport_thread &&
608                       (act != handle || threads[i] != ss->thread))
609                     {
610                       err = __thread_resume (threads[i]);
611                       assert_perror (err);
612                     }
613                   err = __mach_port_deallocate (__mach_task_self (),
614                                                 threads[i]);
615                   assert_perror (err);
616                 }
617               __vm_deallocate (__mach_task_self (),
618                                (vm_address_t) threads,
619                                nthreads * sizeof *threads);
620               _hurd_stopped = 0;
621               /* The thread that will run the handler is already suspended.  */
622               ss_suspended = 1;
623             }
624         }
625     }
626
627   if (_hurd_orphaned && act == stop &&
628       (__sigmask (signo) & (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) |
629                             __sigmask (SIGTSTP))))
630     {
631       /* If we would ordinarily stop for a job control signal, but we are
632          orphaned so noone would ever notice and continue us again, we just
633          quietly die, alone and in the dark.  */
634       sigcode = signo;
635       signo = SIGKILL;
636       act = term;
637     }
638
639   /* Handle receipt of a blocked signal, or any signal while stopped.
640      It matters that we test ACT first here, because we must never pass
641      SIGNO==0 to __sigismember.  */
642   if ((act != ignore && __sigismember (&ss->blocked, signo)) ||
643       (signo != SIGKILL && _hurd_stopped))
644     {
645       mark_pending ();
646       act = ignore;
647     }
648
649   /* Perform the chosen action for the signal.  */
650   switch (act)
651     {
652     case stop:
653       if (_hurd_stopped)
654         {
655           /* We are already stopped, but receiving an untraced stop
656              signal.  Instead of resuming and suspending again, just
657              notify the proc server of the new stop signal.  */
658           error_t err = __USEPORT (PROC, __proc_mark_stop (port, signo));
659           assert_perror (err);
660         }
661       else
662         /* Suspend the process.  */
663         suspend ();
664       break;
665
666     case ignore:
667       /* Nobody cares about this signal.  */
668       break;
669
670     sigbomb:
671       /* We got a fault setting up the stack frame for the handler.
672          Nothing to do but die; BSD gets SIGILL in this case.  */
673       sigcode = signo;  /* XXX ? */
674       signo = SIGILL;
675       act = core;
676       /* FALLTHROUGH */
677
678     case term:                  /* Time to die.  */
679     case core:                  /* And leave a rotting corpse.  */
680       /* Have the proc server stop all other threads in our task.  */
681       err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
682       assert_perror (err);
683       /* No more user instructions will be executed.
684          The signal can now be considered delivered.  */
685       reply ();
686       /* Abort all server operations now in progress.  */
687       abort_all_rpcs (signo, &thread_state, 0);
688
689       {
690         int status = W_EXITCODE (0, signo);
691         /* Do a core dump if desired.  Only set the wait status bit saying we
692            in fact dumped core if the operation was actually successful.  */
693         if (act == core && write_corefile (signo, sigcode, sigerror))
694           status |= WCOREFLAG;
695         /* Tell proc how we died and then stick the saber in the gut.  */
696         _hurd_exit (status);
697         /* NOTREACHED */
698       }
699
700     case handle:
701       /* Call a handler for this signal.  */
702       {
703         struct sigcontext *scp, ocontext;
704         int wait_for_reply, state_changed;
705
706         /* Stop the thread and abort its pending RPC operations.  */
707         if (! ss_suspended)
708           {
709             err = __thread_suspend (ss->thread);
710             assert_perror (err);
711           }
712
713         /* Abort the thread's kernel context, so any pending message send
714            or receive completes immediately or aborts.  If an interruptible
715            RPC is in progress, abort_rpcs will do this.  But we must always
716            do it before fetching the thread's state, because
717            thread_get_state is never kosher before thread_abort.  */
718         abort_thread (ss, &thread_state, NULL, 0, 0);
719
720         if (ss->context)
721           {
722             /* We have a previous sigcontext that sigreturn was about
723                to restore when another signal arrived.  */
724
725             mach_port_t *loc;
726
727             if (_hurdsig_catch_fault (SIGSEGV))
728               {
729                 assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
730                         _hurdsig_fault_sigcode < (long int) (ss->context + 1));
731                 /* We faulted reading the thread's stack.  Forget that
732                    context and pretend it wasn't there.  It almost
733                    certainly crash if this handler returns, but that's it's
734                    problem.  */
735                 ss->context = NULL;
736               }
737             else
738               {
739                 /* Copy the context from the thread's stack before
740                    we start diddling the stack to set up the handler.  */
741                 ocontext = *ss->context;
742                 ss->context = &ocontext;
743               }
744             _hurdsig_end_catch_fault ();
745             
746             if (! machine_get_basic_state (ss->thread, &thread_state))
747               goto sigbomb;
748             loc = interrupted_reply_port_location (&thread_state);
749             if (loc && *loc != MACH_PORT_NULL)
750               /* This is the reply port for the context which called
751                  sigreturn.  Since we are abandoning that context entirely
752                  and restoring SS->context instead, destroy this port.  */
753               __mach_port_destroy (__mach_task_self (), *loc);
754
755             /* The thread was in sigreturn, not in any interruptible RPC.  */
756             wait_for_reply = 0;
757
758             assert (! ss->critical_section);
759           }
760         else
761           {
762             wait_for_reply = (abort_rpcs (ss, signo,
763                                           &thread_state, &state_changed,
764                                           &reply_port, reply_port_type,
765                                           untraced)
766                               != MACH_PORT_NULL);
767
768             if (ss->critical_section)
769               {
770                 /* The thread is in a critical section.  Mark the signal as
771                    pending.  When it finishes the critical section, it will
772                    check for pending signals.  */
773                 mark_pending ();
774                 assert (! state_changed);
775                 __thread_resume (ss->thread);
776                 break;
777               }
778           }
779
780         /* Call the machine-dependent function to set the thread up
781            to run the signal handler, and preserve its old context.  */
782         scp = _hurd_setup_sighandler (ss, handler,
783                                       signo, sigcode,
784                                       wait_for_reply, &thread_state);
785         if (scp == NULL)
786           goto sigbomb;
787
788         /* Set the machine-independent parts of the signal context.  */
789
790         {
791           /* Fetch the thread variable for the MiG reply port,
792              and set it to MACH_PORT_NULL.  */
793           mach_port_t *loc = interrupted_reply_port_location (&thread_state);
794           if (loc)
795             {
796               scp->sc_reply_port = *loc;
797               *loc = MACH_PORT_NULL;
798             }
799           else
800             scp->sc_reply_port = MACH_PORT_NULL;
801
802           /* Save the intr_port in use by the interrupted code,
803              and clear the cell before running the trampoline.  */
804           scp->sc_intr_port = ss->intr_port;
805           ss->intr_port = MACH_PORT_NULL;
806
807           if (ss->context)
808             {
809               /* After the handler runs we will restore to the state in
810                  SS->context, not the state of the thread now.  So restore
811                  that context's reply port and intr port.  */
812
813               scp->sc_reply_port = ss->context->sc_reply_port;
814               scp->sc_intr_port = ss->context->sc_intr_port;
815
816               ss->context = NULL;
817             }
818         }
819
820         /* Backdoor extra argument to signal handler.  */
821         scp->sc_error = sigerror;
822
823         /* Block SIGNO and requested signals while running the handler.  */
824         scp->sc_mask = ss->blocked;
825         ss->blocked |= __sigmask (signo) | ss->actions[signo].sa_mask;
826
827         /* Start the thread running the handler (or possibly waiting for an
828            RPC reply before running the handler).  */
829         err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
830                                   (natural_t *) &thread_state.basic,
831                                   MACHINE_THREAD_STATE_COUNT);
832         assert_perror (err);
833         err = __thread_resume (ss->thread);
834         assert_perror (err);
835         thread_state.set = 0;   /* Everything we know is now wrong.  */
836         break;
837       }
838     }
839
840   /* The signal has either been ignored or is now being handled.  We can
841      consider it delivered and reply to the killer.  The exception is
842      signal 0, which can be sent by a user thread to make us check for
843      pending signals.  In that case we want to deliver the pending signals
844      before replying.  */
845   if (signo != 0)
846     reply ();
847
848   /* We get here unless the signal was fatal.  We still hold SS->lock.
849      Check for pending signals, and loop to post them.  */
850   {
851     /* Return nonzero if SS has any signals pending we should worry about.
852        We don't worry about any pending signals if we are stopped, nor if
853        SS is in a critical section.  We are guaranteed to get a sig_post
854        message before any of them become deliverable: either the SIGCONT
855        signal, or a sig_post with SIGNO==0 as an explicit poll when the
856        thread finishes its critical section.  */
857     inline int signals_pending (void)
858       {
859         if (_hurd_stopped || ss->critical_section)
860           return 0;
861         return pending = ss->pending & ~ss->blocked;
862       }
863
864     if (signals_pending ())
865       {
866       pending:
867         for (signo = 1; signo < NSIG; ++signo)
868           if (__sigismember (&pending, signo))
869             {
870               __sigdelset (&ss->pending, signo);
871               sigcode = ss->pending_data[signo].code;
872               sigerror = ss->pending_data[signo].error;
873               __spin_unlock (&ss->lock);
874               goto post_signal;
875             }
876       }
877
878     /* No pending signals left undelivered for this thread.
879        If we were sent signal 0, we need to check for pending
880        signals for all threads.  */
881     if (signo == 0)
882       {
883         __spin_unlock (&ss->lock);
884         __mutex_lock (&_hurd_siglock);
885         for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
886           {
887             __spin_lock (&ss->lock);
888             if (signals_pending ())
889               goto pending;
890             __spin_unlock (&ss->lock);
891           }
892         __mutex_unlock (&_hurd_siglock);
893       }
894     else
895       {
896         /* No more signals pending; SS->lock is still locked.
897            Wake up any sigsuspend call that is blocking SS->thread.  */
898         if (ss->suspended != MACH_PORT_NULL)
899           {
900             /* There is a sigsuspend waiting.  Tell it to wake up.  */
901             error_t err;
902             mach_msg_header_t msg;
903             err = __mach_port_insert_right (__mach_task_self (),
904                                             ss->suspended, ss->suspended,
905                                             MACH_MSG_TYPE_MAKE_SEND);
906             assert_perror (err);
907             msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MOVE_SEND, 0);
908             msg.msgh_remote_port = ss->suspended;
909             msg.msgh_local_port = MACH_PORT_NULL;
910             /* These values do not matter.  */
911             msg.msgh_id = 8675309; /* Jenny, Jenny.  */
912             msg.msgh_seqno = 17; /* Random.  */
913             ss->suspended = MACH_PORT_NULL;
914             err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
915                               MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
916                               MACH_PORT_NULL);
917             assert_perror (err);
918           }
919         __spin_unlock (&ss->lock);
920       }
921   }
922
923   /* All pending signals delivered to all threads.
924      Now we can send the reply message even for signal 0.  */
925   reply ();
926 }
927 \f
928 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
929    Returns zero if so, otherwise the error code to return to the sender.  */
930
931 static error_t
932 signal_allowed (int signo, mach_port_t refport)
933 {
934   if (signo < 0 || signo >= NSIG)
935     return EINVAL;
936
937   if (refport == __mach_task_self ())
938     /* Can send any signal.  */
939     goto win;
940
941   /* Avoid needing to check for this below.  */
942   if (refport == MACH_PORT_NULL)
943     return EPERM;
944
945   switch (signo)
946     {
947     case SIGINT:
948     case SIGQUIT:
949     case SIGTSTP:
950     case SIGHUP:
951     case SIGINFO:
952     case SIGTTIN:
953     case SIGTTOU:
954       /* Job control signals can be sent by the controlling terminal.  */
955       if (__USEPORT (CTTYID, port == refport))
956         goto win;
957       break;
958
959     case SIGCONT:
960       {
961         /* A continue signal can be sent by anyone in the session.  */
962         mach_port_t sessport;
963         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
964           { 
965             __mach_port_deallocate (__mach_task_self (), sessport);
966             if (refport == sessport)
967               goto win;
968           }
969       }
970       break;
971
972     case SIGIO:
973     case SIGURG:
974       {
975         /* Any io object a file descriptor refers to might send us
976            one of these signals using its async ID port for REFPORT.
977
978            This is pretty wide open; it is not unlikely that some random
979            process can at least open for reading something we have open,
980            get its async ID port, and send us a spurious SIGIO or SIGURG
981            signal.  But BSD is actually wider open than that!--you can set
982            the owner of an io object to any process or process group
983            whatsoever and send them gratuitous signals.
984
985            Someday we could implement some reasonable scheme for
986            authorizing SIGIO and SIGURG signals properly.  */
987
988         int d;
989         __mutex_lock (&_hurd_dtable_lock);
990         for (d = 0; (unsigned int) d < (unsigned int) _hurd_dtablesize; ++d)
991           {
992             struct hurd_userlink ulink;
993             io_t port;
994             mach_port_t asyncid;
995             if (_hurd_dtable[d] == NULL)
996               continue;
997             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
998             if (! __io_get_icky_async_id (port, &asyncid))
999               {
1000                 if (refport == asyncid)
1001                   /* Break out of the loop on the next iteration.  */
1002                   d = -1;
1003                 __mach_port_deallocate (__mach_task_self (), asyncid);
1004               }
1005             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
1006           }
1007         /* If we found a lucky winner, we've set D to -1 in the loop.  */
1008         if (d < 0)
1009           goto win;
1010       }
1011     }
1012
1013   /* If this signal is legit, we have done `goto win' by now.
1014      When we return the error, mig deallocates REFPORT.  */
1015   return EPERM;
1016
1017  win:
1018   /* Deallocate the REFPORT send right; we are done with it.  */
1019   __mach_port_deallocate (__mach_task_self (), refport);
1020
1021   return 0;
1022 }
1023
1024 /* Implement the sig_post RPC from <hurd/msg.defs>;
1025    sent when someone wants us to get a signal.  */
1026 kern_return_t
1027 _S_msg_sig_post (mach_port_t me,
1028                  mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
1029                  int signo,
1030                  mach_port_t refport)
1031 {
1032   error_t err;
1033
1034   if (err = signal_allowed (signo, refport))
1035     return err;
1036
1037   /* Post the signal to the designated signal-receiving thread.  This will
1038      reply when the signal can be considered delivered.  */
1039   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1040                               signo, 0, 0, reply_port, reply_port_type,
1041                               0); /* Stop if traced.  */
1042
1043   return MIG_NO_REPLY;          /* Already replied.  */
1044 }
1045
1046 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1047    sent when the debugger wants us to really get a signal
1048    even if we are traced.  */
1049 kern_return_t
1050 _S_msg_sig_post_untraced (mach_port_t me,
1051                           mach_port_t reply_port,
1052                           mach_msg_type_name_t reply_port_type,
1053                           int signo,
1054                           mach_port_t refport)
1055 {
1056   error_t err;
1057
1058   if (err = signal_allowed (signo, refport))
1059     return err;
1060
1061   /* Post the signal to the designated signal-receiving thread.  This will
1062      reply when the signal can be considered delivered.  */
1063   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1064                               signo, 0, 0, reply_port, reply_port_type,
1065                               1); /* Untraced flag. */
1066
1067   return MIG_NO_REPLY;          /* Already replied.  */
1068 }
1069 \f
1070 extern void __mig_init (void *);
1071
1072 #include <mach/task_special_ports.h>
1073
1074 /* Initialize the message port and _hurd_sigthread and start the signal
1075    thread.  */
1076
1077 void
1078 _hurdsig_init (void)
1079 {
1080   error_t err;
1081   vm_size_t stacksize;
1082
1083   __mutex_init (&_hurd_siglock);
1084
1085   if (err = __mach_port_allocate (__mach_task_self (),
1086                                   MACH_PORT_RIGHT_RECEIVE,
1087                                   &_hurd_msgport))
1088     __libc_fatal ("hurd: Can't create message port receive right\n");
1089   
1090   /* Make a send right to the signal port.  */
1091   if (err = __mach_port_insert_right (__mach_task_self (),
1092                                       _hurd_msgport,
1093                                       _hurd_msgport,
1094                                       MACH_MSG_TYPE_MAKE_SEND))
1095     __libc_fatal ("hurd: Can't create send right to message port\n");
1096
1097   /* Set the default thread to receive task-global signals
1098      to this one, the main (first) user thread.  */
1099   _hurd_sigthread = __mach_thread_self ();
1100
1101   /* Start the signal thread listening on the message port.  */
1102
1103   if (err = __thread_create (__mach_task_self (), &_hurd_msgport_thread))
1104     __libc_fatal ("hurd: Can't create signal thread\n");
1105
1106   stacksize = __vm_page_size * 4; /* Small stack for signal thread.  */
1107   if (err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1108                                  _hurd_msgport_receive,
1109                                  (vm_address_t *) &__hurd_sigthread_stack_base,
1110                                  &stacksize))
1111     __libc_fatal ("hurd: Can't setup signal thread\n");
1112
1113   __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1114   __hurd_sigthread_variables =
1115     malloc (__hurd_threadvar_max * sizeof (unsigned long int));
1116   if (__hurd_sigthread_variables == NULL)
1117     __libc_fatal ("hurd: Can't allocate thread variables for signal thread\n");
1118
1119   /* Reinitialize the MiG support routines so they will use a per-thread
1120      variable for the cached reply port.  */
1121   __mig_init ((void *) __hurd_sigthread_stack_base);
1122
1123   if (err = __thread_resume (_hurd_msgport_thread))
1124     __libc_fatal ("hurd: Can't resume signal thread\n");
1125     
1126 #if 0                           /* Don't confuse poor gdb.  */
1127   /* Receive exceptions on the signal port.  */
1128   __task_set_special_port (__mach_task_self (),
1129                            TASK_EXCEPTION_PORT, _hurd_msgport);
1130 #endif
1131 }
1132 \f                               /* XXXX */
1133 /* Reauthenticate with the proc server.  */
1134
1135 static void
1136 reauth_proc (mach_port_t new)
1137 {
1138   mach_port_t ref, ignore;
1139
1140   ref = __mach_reply_port ();
1141   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1142                        __proc_reauthenticate (port, ref,
1143                                               MACH_MSG_TYPE_MAKE_SEND) ||
1144                        __auth_user_authenticate (new, port, ref,
1145                                                  MACH_MSG_TYPE_MAKE_SEND,
1146                                                  &ignore))
1147       && ignore != MACH_PORT_NULL)
1148     __mach_port_deallocate (__mach_task_self (), ignore);
1149   __mach_port_destroy (__mach_task_self (), ref);
1150
1151   (void) &reauth_proc;          /* Silence compiler warning.  */
1152 }
1153 text_set_element (_hurd_reauth_hook, reauth_proc);
1154 \f
1155 /* Like `getenv', but safe for the signal thread to run.
1156    If the environment is trashed, this will just return NULL.  */
1157
1158 const char *
1159 _hurdsig_getenv (const char *variable)
1160 {
1161   if (_hurdsig_catch_fault (SIGSEGV))
1162     /* We bombed in getenv.  */
1163     return NULL;
1164   else
1165     {
1166       const char *value = getenv (variable);
1167       /* Fault now if VALUE is a bogus string.  */
1168       (void) strlen (value);
1169       _hurdsig_end_catch_fault ();
1170       return value;
1171     }
1172 }