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