Merge branch 'elf-move'
[platform/upstream/glibc.git] / hurd / hurdsig.c
1 /* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,2001,2002,2005,2008
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, see
17    <http://www.gnu.org/licenses/>.  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <cthreads.h>           /* For `struct mutex'.  */
24 #include <mach.h>
25 #include <mach/thread_switch.h>
26
27 #include <hurd.h>
28 #include <hurd/id.h>
29 #include <hurd/signal.h>
30
31 #include "hurdfault.h"
32 #include "hurdmalloc.h"         /* XXX */
33 #include "../locale/localeinfo.h"
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       if (detail->exc)
746         /* Blocking or ignoring a machine exception is fatal.
747            Otherwise we could just spin on the faulting instruction.  */
748         goto fatal;
749
750       /* Nobody cares about this signal.  If there was a call to resume
751          above in SIGCONT processing and we've left a thread suspended,
752          now's the time to set it going. */
753       if (ss_suspended)
754         {
755           err = __thread_resume (ss->thread);
756           assert_perror (err);
757           ss_suspended = 0;
758         }
759       break;
760
761     sigbomb:
762       /* We got a fault setting up the stack frame for the handler.
763          Nothing to do but die; BSD gets SIGILL in this case.  */
764       detail->code = signo;     /* XXX ? */
765       signo = SIGILL;
766
767     fatal:
768       act = core;
769       /* FALLTHROUGH */
770
771     case term:                  /* Time to die.  */
772     case core:                  /* And leave a rotting corpse.  */
773       /* Have the proc server stop all other threads in our task.  */
774       err = __USEPORT (PROC, __proc_dostop (port, _hurd_msgport_thread));
775       assert_perror (err);
776       /* No more user instructions will be executed.
777          The signal can now be considered delivered.  */
778       reply ();
779       /* Abort all server operations now in progress.  */
780       abort_all_rpcs (signo, &thread_state, 0);
781
782       {
783         int status = W_EXITCODE (0, signo);
784         /* Do a core dump if desired.  Only set the wait status bit saying we
785            in fact dumped core if the operation was actually successful.  */
786         if (act == core && write_corefile (signo, detail))
787           status |= WCOREFLAG;
788         /* Tell proc how we died and then stick the saber in the gut.  */
789         _hurd_exit (status);
790         /* NOTREACHED */
791       }
792
793     case handle:
794       /* Call a handler for this signal.  */
795       {
796         struct sigcontext *scp, ocontext;
797         int wait_for_reply, state_changed;
798
799         /* Stop the thread and abort its pending RPC operations.  */
800         if (! ss_suspended)
801           {
802             err = __thread_suspend (ss->thread);
803             assert_perror (err);
804           }
805
806         /* Abort the thread's kernel context, so any pending message send
807            or receive completes immediately or aborts.  If an interruptible
808            RPC is in progress, abort_rpcs will do this.  But we must always
809            do it before fetching the thread's state, because
810            thread_get_state is never kosher before thread_abort.  */
811         abort_thread (ss, &thread_state, NULL);
812
813         if (ss->context)
814           {
815             /* We have a previous sigcontext that sigreturn was about
816                to restore when another signal arrived.  */
817
818             mach_port_t *loc;
819
820             if (_hurdsig_catch_memory_fault (ss->context))
821               {
822                 /* We faulted reading the thread's stack.  Forget that
823                    context and pretend it wasn't there.  It almost
824                    certainly crash if this handler returns, but that's it's
825                    problem.  */
826                 ss->context = NULL;
827               }
828             else
829               {
830                 /* Copy the context from the thread's stack before
831                    we start diddling the stack to set up the handler.  */
832                 ocontext = *ss->context;
833                 ss->context = &ocontext;
834               }
835             _hurdsig_end_catch_fault ();
836
837             if (! machine_get_basic_state (ss->thread, &thread_state))
838               goto sigbomb;
839             loc = interrupted_reply_port_location (&thread_state, 1);
840             if (loc && *loc != MACH_PORT_NULL)
841               /* This is the reply port for the context which called
842                  sigreturn.  Since we are abandoning that context entirely
843                  and restoring SS->context instead, destroy this port.  */
844               __mach_port_destroy (__mach_task_self (), *loc);
845
846             /* The thread was in sigreturn, not in any interruptible RPC.  */
847             wait_for_reply = 0;
848
849             assert (! __spin_lock_locked (&ss->critical_section_lock));
850           }
851         else
852           {
853             int crit = __spin_lock_locked (&ss->critical_section_lock);
854
855             wait_for_reply
856               = (_hurdsig_abort_rpcs (ss,
857                                       /* In a critical section, any RPC
858                                          should be cancelled instead of
859                                          restarted, regardless of
860                                          SA_RESTART, so the entire
861                                          "atomic" operation can be aborted
862                                          as a unit.  */
863                                       crit ? 0 : signo, 1,
864                                       &thread_state, &state_changed,
865                                       &reply)
866                  != MACH_PORT_NULL);
867
868             if (crit)
869               {
870                 /* The thread is in a critical section.  Mark the signal as
871                    pending.  When it finishes the critical section, it will
872                    check for pending signals.  */
873                 mark_pending ();
874                 if (state_changed)
875                   /* Some cases of interrupting an RPC must change the
876                      thread state to back out the call.  Normally this
877                      change is rolled into the warping to the handler and
878                      sigreturn, but we are not running the handler now
879                      because the thread is in a critical section.  Instead,
880                      mutate the thread right away for the RPC interruption
881                      and resume it; the RPC will return early so the
882                      critical section can end soon.  */
883                   __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
884                                       (natural_t *) &thread_state.basic,
885                                       MACHINE_THREAD_STATE_COUNT);
886                 /* */
887                 ss->intr_port = MACH_PORT_NULL;
888                 __thread_resume (ss->thread);
889                 break;
890               }
891           }
892
893         /* Call the machine-dependent function to set the thread up
894            to run the signal handler, and preserve its old context.  */
895         scp = _hurd_setup_sighandler (ss, handler, signo, detail,
896                                       wait_for_reply, &thread_state);
897         if (scp == NULL)
898           goto sigbomb;
899
900         /* Set the machine-independent parts of the signal context.  */
901
902         {
903           /* Fetch the thread variable for the MiG reply port,
904              and set it to MACH_PORT_NULL.  */
905           mach_port_t *loc = interrupted_reply_port_location (&thread_state,
906                                                               1);
907           if (loc)
908             {
909               scp->sc_reply_port = *loc;
910               *loc = MACH_PORT_NULL;
911             }
912           else
913             scp->sc_reply_port = MACH_PORT_NULL;
914
915           /* Save the intr_port in use by the interrupted code,
916              and clear the cell before running the trampoline.  */
917           scp->sc_intr_port = ss->intr_port;
918           ss->intr_port = MACH_PORT_NULL;
919
920           if (ss->context)
921             {
922               /* After the handler runs we will restore to the state in
923                  SS->context, not the state of the thread now.  So restore
924                  that context's reply port and intr port.  */
925
926               scp->sc_reply_port = ss->context->sc_reply_port;
927               scp->sc_intr_port = ss->context->sc_intr_port;
928
929               ss->context = NULL;
930             }
931         }
932
933         /* Backdoor extra argument to signal handler.  */
934         scp->sc_error = detail->error;
935
936         /* Block requested signals while running the handler.  */
937         scp->sc_mask = ss->blocked;
938         __sigorset (&ss->blocked, &ss->blocked, &ss->actions[signo].sa_mask);
939
940         /* Also block SIGNO unless we're asked not to.  */
941         if (! (ss->actions[signo].sa_flags & (SA_RESETHAND | SA_NODEFER)))
942           __sigaddset (&ss->blocked, signo);
943
944         /* Reset to SIG_DFL if requested.  SIGILL and SIGTRAP cannot
945            be automatically reset when delivered; the system silently
946            enforces this restriction.  */
947         if (ss->actions[signo].sa_flags & SA_RESETHAND
948             && signo != SIGILL && signo != SIGTRAP)
949           ss->actions[signo].sa_handler = SIG_DFL;
950
951         /* Start the thread running the handler (or possibly waiting for an
952            RPC reply before running the handler).  */
953         err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
954                                   (natural_t *) &thread_state.basic,
955                                   MACHINE_THREAD_STATE_COUNT);
956         assert_perror (err);
957         err = __thread_resume (ss->thread);
958         assert_perror (err);
959         thread_state.set = 0;   /* Everything we know is now wrong.  */
960         break;
961       }
962     }
963
964   /* The signal has either been ignored or is now being handled.  We can
965      consider it delivered and reply to the killer.  */
966   reply ();
967
968   /* We get here unless the signal was fatal.  We still hold SS->lock.
969      Check for pending signals, and loop to post them.  */
970   {
971     /* Return nonzero if SS has any signals pending we should worry about.
972        We don't worry about any pending signals if we are stopped, nor if
973        SS is in a critical section.  We are guaranteed to get a sig_post
974        message before any of them become deliverable: either the SIGCONT
975        signal, or a sig_post with SIGNO==0 as an explicit poll when the
976        thread finishes its critical section.  */
977     inline int signals_pending (void)
978       {
979         if (_hurd_stopped || __spin_lock_locked (&ss->critical_section_lock))
980           return 0;
981         return pending = ss->pending & ~ss->blocked;
982       }
983
984   check_pending_signals:
985     untraced = 0;
986
987     if (signals_pending ())
988       {
989         for (signo = 1; signo < NSIG; ++signo)
990           if (__sigismember (&pending, signo))
991             {
992             deliver_pending:
993               __sigdelset (&ss->pending, signo);
994               *detail = ss->pending_data[signo];
995               __spin_unlock (&ss->lock);
996               goto post_signal;
997             }
998       }
999
1000     /* No pending signals left undelivered for this thread.
1001        If we were sent signal 0, we need to check for pending
1002        signals for all threads.  */
1003     if (signo == 0)
1004       {
1005         __spin_unlock (&ss->lock);
1006         __mutex_lock (&_hurd_siglock);
1007         for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
1008           {
1009             __spin_lock (&ss->lock);
1010             for (signo = 1; signo < NSIG; ++signo)
1011               if (__sigismember (&ss->pending, signo)
1012                   && (!__sigismember (&ss->blocked, signo)
1013                       /* We "deliver" immediately pending blocked signals whose
1014                          action might be to ignore, so that if ignored they are
1015                          dropped right away.  */
1016                       || ss->actions[signo].sa_handler == SIG_IGN
1017                       || ss->actions[signo].sa_handler == SIG_DFL))
1018                 {
1019                   mutex_unlock (&_hurd_siglock);
1020                   goto deliver_pending;
1021                 }
1022             __spin_unlock (&ss->lock);
1023           }
1024         __mutex_unlock (&_hurd_siglock);
1025       }
1026     else
1027       {
1028         /* No more signals pending; SS->lock is still locked.
1029            Wake up any sigsuspend call that is blocking SS->thread.  */
1030         if (ss->suspended != MACH_PORT_NULL)
1031           {
1032             /* There is a sigsuspend waiting.  Tell it to wake up.  */
1033             error_t err;
1034             mach_msg_header_t msg;
1035             msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
1036             msg.msgh_remote_port = ss->suspended;
1037             msg.msgh_local_port = MACH_PORT_NULL;
1038             /* These values do not matter.  */
1039             msg.msgh_id = 8675309; /* Jenny, Jenny.  */
1040             ss->suspended = MACH_PORT_NULL;
1041             err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
1042                               MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
1043                               MACH_PORT_NULL);
1044             assert_perror (err);
1045           }
1046         __spin_unlock (&ss->lock);
1047       }
1048   }
1049
1050   /* All pending signals delivered to all threads.
1051      Now we can send the reply message even for signal 0.  */
1052   reply ();
1053 }
1054 \f
1055 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
1056    Returns zero if so, otherwise the error code to return to the sender.  */
1057
1058 static error_t
1059 signal_allowed (int signo, mach_port_t refport)
1060 {
1061   if (signo < 0 || signo >= NSIG)
1062     return EINVAL;
1063
1064   if (refport == __mach_task_self ())
1065     /* Can send any signal.  */
1066     goto win;
1067
1068   /* Avoid needing to check for this below.  */
1069   if (refport == MACH_PORT_NULL)
1070     return EPERM;
1071
1072   switch (signo)
1073     {
1074     case SIGINT:
1075     case SIGQUIT:
1076     case SIGTSTP:
1077     case SIGHUP:
1078     case SIGINFO:
1079     case SIGTTIN:
1080     case SIGTTOU:
1081     case SIGWINCH:
1082       /* Job control signals can be sent by the controlling terminal.  */
1083       if (__USEPORT (CTTYID, port == refport))
1084         goto win;
1085       break;
1086
1087     case SIGCONT:
1088       {
1089         /* A continue signal can be sent by anyone in the session.  */
1090         mach_port_t sessport;
1091         if (! __USEPORT (PROC, __proc_getsidport (port, &sessport)))
1092           {
1093             __mach_port_deallocate (__mach_task_self (), sessport);
1094             if (refport == sessport)
1095               goto win;
1096           }
1097       }
1098       break;
1099
1100     case SIGIO:
1101     case SIGURG:
1102       {
1103         /* Any io object a file descriptor refers to might send us
1104            one of these signals using its async ID port for REFPORT.
1105
1106            This is pretty wide open; it is not unlikely that some random
1107            process can at least open for reading something we have open,
1108            get its async ID port, and send us a spurious SIGIO or SIGURG
1109            signal.  But BSD is actually wider open than that!--you can set
1110            the owner of an io object to any process or process group
1111            whatsoever and send them gratuitous signals.
1112
1113            Someday we could implement some reasonable scheme for
1114            authorizing SIGIO and SIGURG signals properly.  */
1115
1116         int d;
1117         int lucky = 0;          /* True if we find a match for REFPORT.  */
1118         __mutex_lock (&_hurd_dtable_lock);
1119         for (d = 0; !lucky && (unsigned) d < (unsigned) _hurd_dtablesize; ++d)
1120           {
1121             struct hurd_userlink ulink;
1122             io_t port;
1123             mach_port_t asyncid;
1124             if (_hurd_dtable[d] == NULL)
1125               continue;
1126             port = _hurd_port_get (&_hurd_dtable[d]->port, &ulink);
1127             if (! __io_get_icky_async_id (port, &asyncid))
1128               {
1129                 if (refport == asyncid)
1130                   /* Break out of the loop on the next iteration.  */
1131                   lucky = 1;
1132                 __mach_port_deallocate (__mach_task_self (), asyncid);
1133               }
1134             _hurd_port_free (&_hurd_dtable[d]->port, &ulink, port);
1135           }
1136         __mutex_unlock (&_hurd_dtable_lock);
1137         /* If we found a lucky winner, we've set D to -1 in the loop.  */
1138         if (lucky)
1139           goto win;
1140       }
1141     }
1142
1143   /* If this signal is legit, we have done `goto win' by now.
1144      When we return the error, mig deallocates REFPORT.  */
1145   return EPERM;
1146
1147  win:
1148   /* Deallocate the REFPORT send right; we are done with it.  */
1149   __mach_port_deallocate (__mach_task_self (), refport);
1150
1151   return 0;
1152 }
1153
1154 /* Implement the sig_post RPC from <hurd/msg.defs>;
1155    sent when someone wants us to get a signal.  */
1156 kern_return_t
1157 _S_msg_sig_post (mach_port_t me,
1158                  mach_port_t reply_port, mach_msg_type_name_t reply_port_type,
1159                  int signo, natural_t sigcode,
1160                  mach_port_t refport)
1161 {
1162   error_t err;
1163   struct hurd_signal_detail d;
1164
1165   if (err = signal_allowed (signo, refport))
1166     return err;
1167
1168   d.code = sigcode;
1169   d.exc = 0;
1170
1171   /* Post the signal to the designated signal-receiving thread.  This will
1172      reply when the signal can be considered delivered.  */
1173   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1174                               signo, &d, reply_port, reply_port_type,
1175                               0); /* Stop if traced.  */
1176
1177   return MIG_NO_REPLY;          /* Already replied.  */
1178 }
1179
1180 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1181    sent when the debugger wants us to really get a signal
1182    even if we are traced.  */
1183 kern_return_t
1184 _S_msg_sig_post_untraced (mach_port_t me,
1185                           mach_port_t reply_port,
1186                           mach_msg_type_name_t reply_port_type,
1187                           int signo, natural_t sigcode,
1188                           mach_port_t refport)
1189 {
1190   error_t err;
1191   struct hurd_signal_detail d;
1192
1193   if (err = signal_allowed (signo, refport))
1194     return err;
1195
1196   d.code = sigcode;
1197   d.exc = 0;
1198
1199   /* Post the signal to the designated signal-receiving thread.  This will
1200      reply when the signal can be considered delivered.  */
1201   _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
1202                               signo, &d, reply_port, reply_port_type,
1203                               1); /* Untraced flag. */
1204
1205   return MIG_NO_REPLY;          /* Already replied.  */
1206 }
1207 \f
1208 extern void __mig_init (void *);
1209
1210 #include <mach/task_special_ports.h>
1211
1212 /* Initialize the message port and _hurd_sigthread and start the signal
1213    thread.  */
1214
1215 void
1216 _hurdsig_init (const int *intarray, size_t intarraysize)
1217 {
1218   error_t err;
1219   vm_size_t stacksize;
1220   struct hurd_sigstate *ss;
1221
1222   __mutex_init (&_hurd_siglock);
1223
1224   err = __mach_port_allocate (__mach_task_self (),
1225                               MACH_PORT_RIGHT_RECEIVE,
1226                               &_hurd_msgport);
1227   assert_perror (err);
1228
1229   /* Make a send right to the signal port.  */
1230   err = __mach_port_insert_right (__mach_task_self (),
1231                                   _hurd_msgport,
1232                                   _hurd_msgport,
1233                                   MACH_MSG_TYPE_MAKE_SEND);
1234   assert_perror (err);
1235
1236   /* Initialize the main thread's signal state.  */
1237   ss = _hurd_self_sigstate ();
1238
1239   /* Copy inherited values from our parent (or pre-exec process state)
1240      into the signal settings of the main thread.  */
1241   if (intarraysize > INIT_SIGMASK)
1242     ss->blocked = intarray[INIT_SIGMASK];
1243   if (intarraysize > INIT_SIGPENDING)
1244     ss->pending = intarray[INIT_SIGPENDING];
1245   if (intarraysize > INIT_SIGIGN && intarray[INIT_SIGIGN] != 0)
1246     {
1247       int signo;
1248       for (signo = 1; signo < NSIG; ++signo)
1249         if (intarray[INIT_SIGIGN] & __sigmask(signo))
1250           ss->actions[signo].sa_handler = SIG_IGN;
1251     }
1252
1253   /* Set the default thread to receive task-global signals
1254      to this one, the main (first) user thread.  */
1255   _hurd_sigthread = ss->thread;
1256
1257   /* Start the signal thread listening on the message port.  */
1258
1259   if (__hurd_threadvar_stack_mask == 0)
1260     {
1261       err = __thread_create (__mach_task_self (), &_hurd_msgport_thread);
1262       assert_perror (err);
1263
1264       stacksize = __vm_page_size * 8; /* Small stack for signal thread.  */
1265       err = __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread,
1266                                  _hurd_msgport_receive,
1267                                  (vm_address_t *) &__hurd_sigthread_stack_base,
1268                                  &stacksize);
1269       assert_perror (err);
1270
1271       __hurd_sigthread_stack_end = __hurd_sigthread_stack_base + stacksize;
1272       __hurd_sigthread_variables =
1273         malloc (__hurd_threadvar_max * sizeof (unsigned long int));
1274       if (__hurd_sigthread_variables == NULL)
1275         __libc_fatal ("hurd: Can't allocate threadvars for signal thread\n");
1276       memset (__hurd_sigthread_variables, 0,
1277               __hurd_threadvar_max * sizeof (unsigned long int));
1278       __hurd_sigthread_variables[_HURD_THREADVAR_LOCALE]
1279         = (unsigned long int) &_nl_global_locale;
1280
1281       /* Reinitialize the MiG support routines so they will use a per-thread
1282          variable for the cached reply port.  */
1283       __mig_init ((void *) __hurd_sigthread_stack_base);
1284
1285       err = __thread_resume (_hurd_msgport_thread);
1286       assert_perror (err);
1287     }
1288   else
1289     {
1290       /* When cthreads is being used, we need to make the signal thread a
1291          proper cthread.  Otherwise it cannot use mutex_lock et al, which
1292          will be the cthreads versions.  Various of the message port RPC
1293          handlers need to take locks, so we need to be able to call into
1294          cthreads code and meet its assumptions about how our thread and
1295          its stack are arranged.  Since cthreads puts it there anyway,
1296          we'll let the signal thread's per-thread variables be found as for
1297          any normal cthread, and just leave the magic __hurd_sigthread_*
1298          values all zero so they'll be ignored.  */
1299 #pragma weak cthread_fork
1300 #pragma weak cthread_detach
1301       cthread_detach (cthread_fork ((cthread_fn_t) &_hurd_msgport_receive, 0));
1302
1303       /* XXX We need the thread port for the signal thread further on
1304          in this thread (see hurdfault.c:_hurdsigfault_init).
1305          Therefore we block until _hurd_msgport_thread is initialized
1306          by the newly created thread.  This really shouldn't be
1307          necessary; we should be able to fetch the thread port for a
1308          cthread from here.  */
1309       while (_hurd_msgport_thread == 0)
1310         __swtch_pri (0);
1311     }
1312
1313   /* Receive exceptions on the signal port.  */
1314 #ifdef TASK_EXCEPTION_PORT
1315   __task_set_special_port (__mach_task_self (),
1316                            TASK_EXCEPTION_PORT, _hurd_msgport);
1317 #elif defined (EXC_MASK_ALL)
1318   __task_set_exception_ports (__mach_task_self (),
1319                               EXC_MASK_ALL & ~(EXC_MASK_SYSCALL
1320                                                | EXC_MASK_MACH_SYSCALL
1321                                                | EXC_MASK_RPC_ALERT),
1322                               _hurd_msgport,
1323                               EXCEPTION_DEFAULT, MACHINE_THREAD_STATE);
1324 #else
1325 # error task_set_exception_port?
1326 #endif
1327
1328   /* Sanity check.  Any pending, unblocked signals should have been
1329      taken by our predecessor incarnation (i.e. parent or pre-exec state)
1330      before packing up our init ints.  This assert is last (not above)
1331      so that signal handling is all set up to handle the abort.  */
1332   assert ((ss->pending &~ ss->blocked) == 0);
1333 }
1334 \f                               /* XXXX */
1335 /* Reauthenticate with the proc server.  */
1336
1337 static void
1338 reauth_proc (mach_port_t new)
1339 {
1340   mach_port_t ref, ignore;
1341
1342   ref = __mach_reply_port ();
1343   if (! HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1344                        __proc_reauthenticate (port, ref,
1345                                               MACH_MSG_TYPE_MAKE_SEND) ||
1346                        __auth_user_authenticate (new, ref,
1347                                                  MACH_MSG_TYPE_MAKE_SEND,
1348                                                  &ignore))
1349       && ignore != MACH_PORT_NULL)
1350     __mach_port_deallocate (__mach_task_self (), ignore);
1351   __mach_port_destroy (__mach_task_self (), ref);
1352
1353   /* Set the owner of the process here too. */
1354   mutex_lock (&_hurd_id.lock);
1355   if (!_hurd_check_ids ())
1356     HURD_PORT_USE (&_hurd_ports[INIT_PORT_PROC],
1357                    __proc_setowner (port,
1358                                     (_hurd_id.gen.nuids
1359                                      ? _hurd_id.gen.uids[0] : 0),
1360                                     !_hurd_id.gen.nuids));
1361   mutex_unlock (&_hurd_id.lock);
1362
1363   (void) &reauth_proc;          /* Silence compiler warning.  */
1364 }
1365 text_set_element (_hurd_reauth_hook, reauth_proc);
1366 \f
1367 /* Like `getenv', but safe for the signal thread to run.
1368    If the environment is trashed, this will just return NULL.  */
1369
1370 const char *
1371 _hurdsig_getenv (const char *variable)
1372 {
1373   if (__libc_enable_secure)
1374     return NULL;
1375
1376   if (_hurdsig_catch_memory_fault (__environ))
1377     /* We bombed in getenv.  */
1378     return NULL;
1379   else
1380     {
1381       const size_t len = strlen (variable);
1382       char *value = NULL;
1383       char *volatile *ep = __environ;
1384       while (*ep)
1385         {
1386           const char *p = *ep;
1387           _hurdsig_fault_preemptor.first = (long int) p;
1388           _hurdsig_fault_preemptor.last = VM_MAX_ADDRESS;
1389           if (! strncmp (p, variable, len) && p[len] == '=')
1390             {
1391               size_t valuelen;
1392               p += len + 1;
1393               valuelen = strlen (p);
1394               _hurdsig_fault_preemptor.last = (long int) (p + valuelen);
1395               value = malloc (++valuelen);
1396               if (value)
1397                 memcpy (value, p, valuelen);
1398               break;
1399             }
1400           _hurdsig_fault_preemptor.first = (long int) ++ep;
1401           _hurdsig_fault_preemptor.last = (long int) (ep + 1);
1402         }
1403       _hurdsig_end_catch_fault ();
1404       return value;
1405     }
1406 }