Sat May 6 11:06:47 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 #define PENDING (!_hurd_stopped && (pending = ss->pending & ~ss->blocked))
851   if (PENDING)
852     {
853     pending:
854       for (signo = 1; signo < NSIG; ++signo)
855         if (__sigismember (&pending, signo))
856           {
857             __sigdelset (&ss->pending, signo);
858             sigcode = ss->pending_data[signo].code;
859             sigerror = ss->pending_data[signo].error;
860             __spin_unlock (&ss->lock);
861             goto post_signal;
862           }
863     }
864
865   /* No pending signals left undelivered for this thread.
866      If we were sent signal 0, we need to check for pending
867      signals for all threads.  */
868   if (signo == 0)
869     {
870       __spin_unlock (&ss->lock);
871       __mutex_lock (&_hurd_siglock);
872       for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
873         {
874           __spin_lock (&ss->lock);
875           if (PENDING)
876             goto pending;
877           __spin_unlock (&ss->lock);
878         }
879       __mutex_unlock (&_hurd_siglock);
880     }
881   else
882     {
883       /* No more signals pending; SS->lock is still locked.
884          Wake up any sigsuspend call that is blocking SS->thread.  */
885       if (ss->suspended != MACH_PORT_NULL)
886         {
887           /* There is a sigsuspend waiting.  Tell it to wake up.  */
888           error_t err;
889           mach_msg_header_t msg;
890           err = __mach_port_insert_right (__mach_task_self (),
891                                           ss->suspended, ss->suspended,
892                                           MACH_MSG_TYPE_MAKE_SEND);
893           assert_perror (err);
894           msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MOVE_SEND, 0);
895           msg.msgh_remote_port = ss->suspended;
896           msg.msgh_local_port = MACH_PORT_NULL;
897           /* These values do not matter.  */
898           msg.msgh_id = 8675309; /* Jenny, Jenny.  */
899           msg.msgh_seqno = 17;  /* Random.  */
900           ss->suspended = MACH_PORT_NULL;
901           err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
902                             MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
903                             MACH_PORT_NULL);
904           assert_perror (err);
905         }
906       __spin_unlock (&ss->lock);
907     }
908
909   /* All pending signals delivered to all threads.
910      Now we can send the reply message even for signal 0.  */
911   reply ();
912 }
913 \f
914 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
915    Returns zero if so, otherwise the error code to return to the sender.  */
916
917 static error_t
918 signal_allowed (int signo, mach_port_t refport)
919 {
920   if (signo < 0 || signo >= NSIG)
921     return EINVAL;
922
923   if (refport == __mach_task_self ())
924     /* Can send any signal.  */
925     goto win;
926
927   /* Avoid needing to check for this below.  */
928   if (refport == MACH_PORT_NULL)
929     return EPERM;
930
931   switch (signo)
932     {
933     case SIGINT:
934     case SIGQUIT:
935     case SIGTSTP:
936     case SIGHUP:
937     case SIGINFO:
938     case SIGTTIN:
939     case SIGTTOU:
940       /* Job control signals can be sent by the controlling terminal.  */
941       if (__USEPORT (CTTYID, port == refport))
942         goto win;
943       break;
944
945     case SIGCONT:
946       {
947         /* A continue signal can be sent by anyone in the session.  */
948         mach_port_t sessport;
949         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
950           { 
951             __mach_port_deallocate (__mach_task_self (), sessport);
952             if (refport == sessport)
953               goto win;
954           }
955       }
956       break;
957
958     case SIGIO:
959     case SIGURG:
960       {
961         /* Any io object a file descriptor refers to might send us
962            one of these signals using its async ID port for REFPORT.
963
964            This is pretty wide open; it is not unlikely that some random
965            process can at least open for reading something we have open,
966            get its async ID port, and send us a spurious SIGIO or SIGURG
967            signal.  But BSD is actually wider open than that!--you can set
968            the owner of an io object to any process or process group
969            whatsoever and send them gratuitous signals.
970
971            Someday we could implement some reasonable scheme for
972            authorizing SIGIO and SIGURG signals properly.  */
973
974         int d;
975         __mutex_lock (&_hurd_dtable_lock);
976         for (d = 0; (unsigned int) d < (unsigned int) _hurd_dtablesize; ++d)
977           {
978             struct hurd_userlink ulink;
979             io_t port;
980             mach_port_t asyncid;
981             if (_hurd_dtable[d] == NULL)
982               continue;
983             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
984             if (! __io_get_icky_async_id (port, &asyncid))
985               {
986                 if (refport == asyncid)
987                   /* Break out of the loop on the next iteration.  */
988                   d = -1;
989                 __mach_port_deallocate (__mach_task_self (), asyncid);
990               }
991             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
992           }
993         /* If we found a lucky winner, we've set D to -1 in the loop.  */
994         if (d < 0)
995           goto win;
996       }
997     }
998
999   /* If this signal is legit, we have done `goto win' by now.
1000      When we return the error, mig deallocates REFPORT.  */
1001   return EPERM;
1002
1003  win:
1004   /* Deallocate the REFPORT send right; we are done with it.  */
1005   __mach_port_deallocate (__mach_task_self (), refport);
1006
1007   return 0;
1008 }
1009
1010 /* Implement the sig_post RPC from <hurd/msg.defs>;
1011    sent when someone wants us to get a signal.  */
1012 kern_return_t
1013 _S_msg_sig_post (mach_port_t me,
1014                  mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
1015                  int signo,
1016                  mach_port_t refport)
1017 {
1018   error_t err;
1019
1020   if (err = signal_allowed (signo, refport))
1021     return err;
1022
1023   /* Post the signal to the designated signal-receiving thread.  This will
1024      reply when the signal can be considered delivered.  */
1025   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1026                               signo, 0, 0, reply_port, reply_port_type,
1027                               0); /* Stop if traced.  */
1028
1029   return MIG_NO_REPLY;          /* Already replied.  */
1030 }
1031
1032 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1033    sent when the debugger wants us to really get a signal
1034    even if we are traced.  */
1035 kern_return_t
1036 _S_msg_sig_post_untraced (mach_port_t me,
1037                           mach_port_t reply_port,
1038                           mach_msg_type_name_t reply_port_type,
1039                           int signo,
1040                           mach_port_t refport)
1041 {
1042   error_t err;
1043
1044   if (err = signal_allowed (signo, refport))
1045     return err;
1046
1047   /* Post the signal to the designated signal-receiving thread.  This will
1048      reply when the signal can be considered delivered.  */
1049   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1050                               signo, 0, 0, reply_port, reply_port_type,
1051                               1); /* Untraced flag. */
1052
1053   return MIG_NO_REPLY;          /* Already replied.  */
1054 }
1055 \f
1056 extern void __mig_init (void *);
1057
1058 #include <mach/task_special_ports.h>
1059
1060 /* Initialize the message port and _hurd_sigthread and start the signal
1061    thread.  */
1062
1063 void
1064 _hurdsig_init (void)
1065 {
1066   error_t err;
1067   vm_size_t stacksize;
1068
1069   __mutex_init (&_hurd_siglock);
1070
1071   if (err = __mach_port_allocate (__mach_task_self (),
1072                                   MACH_PORT_RIGHT_RECEIVE,
1073                                   &_hurd_msgport))
1074     __libc_fatal ("hurd: Can't create message port receive right\n");
1075   
1076   /* Make a send right to the signal port.  */
1077   if (err = __mach_port_insert_right (__mach_task_self (),
1078                                       _hurd_msgport,
1079                                       _hurd_msgport,
1080                                       MACH_MSG_TYPE_MAKE_SEND))
1081     __libc_fatal ("hurd: Can't create send right to message port\n");
1082
1083   /* Set the default thread to receive task-global signals
1084      to this one, the main (first) user thread.  */
1085   _hurd_sigthread = __mach_thread_self ();
1086
1087   /* Start the signal thread listening on the message port.  */
1088
1089   if (err = __thread_create (__mach_task_self (), &_hurd_msgport_thread))
1090     __libc_fatal ("hurd: Can't create signal thread\n");
1091
1092   stacksize = __vm_page_size * 4; /* Small stack for signal thread.  */
1093   if (err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1094                                  _hurd_msgport_receive,
1095                                  (vm_address_t *) &__hurd_sigthread_stack_base,
1096                                  &stacksize))
1097     __libc_fatal ("hurd: Can't setup signal thread\n");
1098
1099   __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1100   __hurd_sigthread_variables =
1101     malloc (__hurd_threadvar_max * sizeof (unsigned long int));
1102   if (__hurd_sigthread_variables == NULL)
1103     __libc_fatal ("hurd: Can't allocate thread variables for signal thread\n");
1104
1105   /* Reinitialize the MiG support routines so they will use a per-thread
1106      variable for the cached reply port.  */
1107   __mig_init ((void *) __hurd_sigthread_stack_base);
1108
1109   if (err = __thread_resume (_hurd_msgport_thread))
1110     __libc_fatal ("hurd: Can't resume signal thread\n");
1111     
1112 #if 0                           /* Don't confuse poor gdb.  */
1113   /* Receive exceptions on the signal port.  */
1114   __task_set_special_port (__mach_task_self (),
1115                            TASK_EXCEPTION_PORT, _hurd_msgport);
1116 #endif
1117 }
1118 \f                               /* XXXX */
1119 /* Reauthenticate with the proc server.  */
1120
1121 static void
1122 reauth_proc (mach_port_t new)
1123 {
1124   mach_port_t ref, ignore;
1125
1126   ref = __mach_reply_port ();
1127   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1128                        __proc_reauthenticate (port, ref,
1129                                               MACH_MSG_TYPE_MAKE_SEND) ||
1130                        __auth_user_authenticate (new, port, ref,
1131                                                  MACH_MSG_TYPE_MAKE_SEND,
1132                                                  &ignore))
1133       && ignore != MACH_PORT_NULL)
1134     __mach_port_deallocate (__mach_task_self (), ignore);
1135   __mach_port_destroy (__mach_task_self (), ref);
1136
1137   (void) &reauth_proc;          /* Silence compiler warning.  */
1138 }
1139 text_set_element (_hurd_reauth_hook, reauth_proc);
1140 \f
1141 /* Like `getenv', but safe for the signal thread to run.
1142    If the environment is trashed, this will just return NULL.  */
1143
1144 const char *
1145 _hurdsig_getenv (const char *variable)
1146 {
1147   if (_hurdsig_catch_fault (SIGSEGV))
1148     /* We bombed in getenv.  */
1149     return NULL;
1150   else
1151     {
1152       const char *value = getenv (variable);
1153       /* Fault now if VALUE is a bogus string.  */
1154       (void) strlen (value);
1155       _hurdsig_end_catch_fault ();
1156       return value;
1157     }
1158 }