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