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