1 /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
22 #include <lock-intern.h> /* For `struct mutex'. */
25 #include <mach/thread_switch.h>
26 #include <mach/mig_support.h>
27 #include <mach/vm_param.h>
31 #include <hurd/signal.h>
33 #include "hurdfault.h"
34 #include "hurdmalloc.h" /* XXX */
35 #include "../locale/localeinfo.h"
37 #include <libc-diag.h>
39 const char *_hurdsig_getenv (const char *);
41 struct mutex _hurd_siglock
;
44 /* Port that receives signals and other miscellaneous messages. */
45 mach_port_t _hurd_msgport
;
47 /* Thread listening on it. */
48 thread_t _hurd_msgport_thread
;
50 /* These are set up by _hurdsig_init. */
51 unsigned long int __hurd_sigthread_stack_base
;
52 unsigned long int __hurd_sigthread_stack_end
;
54 /* Linked-list of per-thread signal state. */
55 struct hurd_sigstate
*_hurd_sigstates
;
57 /* Sigstate for the task-global signals. */
58 struct hurd_sigstate
*_hurd_global_sigstate
;
60 /* Timeout for RPC's after interrupt_operation. */
61 mach_msg_timeout_t _hurd_interrupted_rpc_timeout
= 60000;
64 default_sigaction (struct sigaction actions
[NSIG
])
68 __sigemptyset (&actions
[0].sa_mask
);
69 actions
[0].sa_flags
= SA_RESTART
;
70 actions
[0].sa_handler
= SIG_DFL
;
72 for (signo
= 1; signo
< NSIG
; ++signo
)
73 actions
[signo
] = actions
[0];
76 struct hurd_sigstate
*
77 _hurd_thread_sigstate (thread_t thread
)
79 struct hurd_sigstate
*ss
;
80 __mutex_lock (&_hurd_siglock
);
81 for (ss
= _hurd_sigstates
; ss
!= NULL
; ss
= ss
->next
)
82 if (ss
->thread
== thread
)
86 ss
= malloc (sizeof (*ss
));
88 __libc_fatal ("hurd: Can't allocate sigstate\n");
89 __spin_lock_init (&ss
->critical_section_lock
);
90 __spin_lock_init (&ss
->lock
);
93 /* Initialize default state. */
94 __sigemptyset (&ss
->blocked
);
95 __sigemptyset (&ss
->pending
);
96 memset (&ss
->sigaltstack
, 0, sizeof (ss
->sigaltstack
));
97 ss
->sigaltstack
.ss_flags
|= SS_DISABLE
;
98 ss
->preemptors
= NULL
;
99 ss
->suspended
= MACH_PORT_NULL
;
100 ss
->intr_port
= MACH_PORT_NULL
;
102 ss
->active_resources
= NULL
;
104 ss
->cancel_hook
= NULL
;
106 if (thread
== MACH_PORT_NULL
)
108 /* Process-wide sigstate, use the system defaults. */
109 default_sigaction (ss
->actions
);
111 /* The global sigstate is not added to the _hurd_sigstates list.
112 It is created with _hurd_thread_sigstate (MACH_PORT_NULL)
113 but should be accessed through _hurd_global_sigstate. */
119 /* Use the global actions as a default for new threads. */
120 struct hurd_sigstate
*s
= _hurd_global_sigstate
;
123 __spin_lock (&s
->lock
);
124 memcpy (ss
->actions
, s
->actions
, sizeof (s
->actions
));
125 __spin_unlock (&s
->lock
);
128 default_sigaction (ss
->actions
);
130 ss
->next
= _hurd_sigstates
;
131 _hurd_sigstates
= ss
;
133 err
= __mach_port_mod_refs (__mach_task_self (), thread
,
134 MACH_PORT_RIGHT_SEND
, 1);
136 __libc_fatal ("hurd: Can't add reference on Mach thread\n");
139 __mutex_unlock (&_hurd_siglock
);
142 libc_hidden_def (_hurd_thread_sigstate
)
144 /* Destroy a sigstate structure. Called by libpthread just before the
145 * corresponding thread is terminated. */
147 _hurd_sigstate_delete (thread_t thread
)
149 struct hurd_sigstate
**ssp
, *ss
;
151 __mutex_lock (&_hurd_siglock
);
152 for (ssp
= &_hurd_sigstates
; *ssp
; ssp
= &(*ssp
)->next
)
153 if ((*ssp
)->thread
== thread
)
160 __mutex_unlock (&_hurd_siglock
);
163 if (ss
->thread
!= MACH_PORT_NULL
)
164 __mach_port_deallocate (__mach_task_self (), ss
->thread
);
170 /* Make SS a global receiver, with pthread signal semantics. */
172 _hurd_sigstate_set_global_rcv (struct hurd_sigstate
*ss
)
174 assert (ss
->thread
!= MACH_PORT_NULL
);
175 ss
->actions
[0].sa_handler
= SIG_IGN
;
178 /* Check whether SS is a global receiver. */
180 sigstate_is_global_rcv (const struct hurd_sigstate
*ss
)
182 return (_hurd_global_sigstate
!= NULL
)
183 && (ss
->actions
[0].sa_handler
== SIG_IGN
);
185 libc_hidden_def (_hurd_sigstate_delete
)
187 /* Lock/unlock a hurd_sigstate structure. If the accessors below require
188 it, the global sigstate will be locked as well. */
190 _hurd_sigstate_lock (struct hurd_sigstate
*ss
)
192 if (sigstate_is_global_rcv (ss
))
193 __spin_lock (&_hurd_global_sigstate
->lock
);
194 __spin_lock (&ss
->lock
);
197 _hurd_sigstate_unlock (struct hurd_sigstate
*ss
)
199 __spin_unlock (&ss
->lock
);
200 if (sigstate_is_global_rcv (ss
))
201 __spin_unlock (&_hurd_global_sigstate
->lock
);
203 libc_hidden_def (_hurd_sigstate_set_global_rcv
)
205 /* Retreive a thread's full set of pending signals, including the global
206 ones if appropriate. SS must be locked. */
208 _hurd_sigstate_pending (const struct hurd_sigstate
*ss
)
210 sigset_t pending
= ss
->pending
;
211 if (sigstate_is_global_rcv (ss
))
212 __sigorset (&pending
, &pending
, &_hurd_global_sigstate
->pending
);
216 /* Clear a pending signal and return the associated detailed
217 signal information. SS must be locked, and must have signal SIGNO
218 pending, either directly or through the global sigstate. */
219 static struct hurd_signal_detail
220 sigstate_clear_pending (struct hurd_sigstate
*ss
, int signo
)
222 if (sigstate_is_global_rcv (ss
)
223 && __sigismember (&_hurd_global_sigstate
->pending
, signo
))
225 __sigdelset (&_hurd_global_sigstate
->pending
, signo
);
226 return _hurd_global_sigstate
->pending_data
[signo
];
229 assert (__sigismember (&ss
->pending
, signo
));
230 __sigdelset (&ss
->pending
, signo
);
231 return ss
->pending_data
[signo
];
233 libc_hidden_def (_hurd_sigstate_lock
)
234 libc_hidden_def (_hurd_sigstate_unlock
)
236 /* Retreive a thread's action vector. SS must be locked. */
238 _hurd_sigstate_actions (struct hurd_sigstate
*ss
)
240 if (sigstate_is_global_rcv (ss
))
241 return _hurd_global_sigstate
->actions
;
245 libc_hidden_def (_hurd_sigstate_pending
)
248 /* Signal delivery itself is on this page. */
251 #include <hurd/crash.h>
252 #include <hurd/resource.h>
253 #include <hurd/paths.h>
256 #include <sys/wait.h>
257 #include <thread_state.h>
258 #include <hurd/msg_server.h>
259 #include <hurd/msg_reply.h> /* For __msg_sig_post_reply. */
260 #include <hurd/interrupt.h>
265 /* Call the crash dump server to mummify us before we die.
266 Returns nonzero if a core file was written. */
268 write_corefile (int signo
, const struct hurd_signal_detail
*detail
)
271 mach_port_t coreserver
;
272 file_t file
, coredir
;
275 /* Don't bother locking since we just read the one word. */
276 rlim_t corelimit
= _hurd_rlimits
[RLIMIT_CORE
].rlim_cur
;
279 /* No core dumping, thank you very much. Note that this makes
280 `ulimit -c 0' prevent crash-suspension too, which is probably
281 what the user wanted. */
285 When we have a protocol to make the server return an error
286 for RLIMIT_FSIZE, then tell the corefile fs server the RLIMIT_CORE
287 value in place of the RLIMIT_FSIZE value. */
289 /* First get a port to the core dumping server. */
290 coreserver
= MACH_PORT_NULL
;
291 name
= _hurdsig_getenv ("CRASHSERVER");
293 coreserver
= __file_name_lookup (name
, 0, 0);
294 if (coreserver
== MACH_PORT_NULL
)
295 coreserver
= __file_name_lookup (_SERVERS_CRASH
, 0, 0);
296 if (coreserver
== MACH_PORT_NULL
)
299 /* Get a port to the directory where the new core file will reside. */
300 file
= MACH_PORT_NULL
;
301 name
= _hurdsig_getenv ("COREFILE");
304 coredir
= __file_name_split (name
, (char **) &name
);
305 if (coredir
!= MACH_PORT_NULL
)
306 /* Create the new file, but don't link it into the directory yet. */
307 __dir_mkfile (coredir
, O_WRONLY
|O_CREAT
,
308 0600 & ~_hurd_umask
, /* XXX ? */
311 /* Call the core dumping server to write the core file. */
312 err
= __crash_dump_task (coreserver
,
315 signo
, detail
->code
, detail
->error
,
316 detail
->exc
, detail
->exc_code
, detail
->exc_subcode
,
317 _hurd_ports
[INIT_PORT_CTTYID
].port
,
318 MACH_MSG_TYPE_COPY_SEND
);
319 __mach_port_deallocate (__mach_task_self (), coreserver
);
321 if (! err
&& file
!= MACH_PORT_NULL
)
322 /* The core dump into FILE succeeded, so now link it into the
324 err
= __dir_link (coredir
, file
, name
, 1);
325 __mach_port_deallocate (__mach_task_self (), file
);
326 __mach_port_deallocate (__mach_task_self (), coredir
);
327 return !err
&& file
!= MACH_PORT_NULL
;
331 /* The lowest-numbered thread state flavor value is 1,
332 so we use bit 0 in machine_thread_all_state.set to
333 record whether we have done thread_abort. */
334 #define THREAD_ABORTED 1
336 /* SS->thread is suspended. Abort the thread and get its basic state. */
338 abort_thread (struct hurd_sigstate
*ss
, struct machine_thread_all_state
*state
,
339 void (*reply
) (void))
341 assert (ss
->thread
!= MACH_PORT_NULL
);
343 if (!(state
->set
& THREAD_ABORTED
))
345 error_t err
= __thread_abort (ss
->thread
);
347 /* Clear all thread state flavor set bits, because thread_abort may
348 have changed the state. */
349 state
->set
= THREAD_ABORTED
;
355 machine_get_basic_state (ss
->thread
, state
);
358 /* Find the location of the MiG reply port cell in use by the thread whose
359 state is described by THREAD_STATE. If SIGTHREAD is nonzero, make sure
360 that this location can be set without faulting, or else return NULL. */
363 interrupted_reply_port_location (thread_t thread
,
364 struct machine_thread_all_state
*thread_state
,
367 mach_port_t
*portloc
= &THREAD_TCB(thread
, thread_state
)->reply_port
;
369 if (sigthread
&& _hurdsig_catch_memory_fault (portloc
))
370 /* Faulted trying to read the TCB. */
373 DIAG_PUSH_NEEDS_COMMENT
;
374 /* GCC 6 and before seem to be confused by the setjmp call inside
375 _hurdsig_catch_memory_fault and think that we may be returning a second
376 time to here with portloc uninitialized (but we never do). */
377 DIAG_IGNORE_NEEDS_COMMENT (6, "-Wmaybe-uninitialized");
378 /* Fault now if this pointer is bogus. */
379 *(volatile mach_port_t
*) portloc
= *portloc
;
380 DIAG_POP_NEEDS_COMMENT
;
383 _hurdsig_end_catch_fault ();
388 #include <hurd/sigpreempt.h>
389 #include <intr-msg.h>
391 /* Timeout on interrupt_operation calls. */
392 mach_msg_timeout_t _hurdsig_interrupt_timeout
= 1000;
394 /* SS->thread is suspended.
396 Abort any interruptible RPC operation the thread is doing.
398 This uses only the constant member SS->thread and the unlocked, atomically
399 set member SS->intr_port, so no locking is needed.
401 If successfully sent an interrupt_operation and therefore the thread should
402 wait for its pending RPC to return (possibly EINTR) before taking the
403 incoming signal, returns the reply port to be received on. Otherwise
404 returns MACH_PORT_NULL.
406 SIGNO is used to find the applicable SA_RESTART bit. If SIGNO is zero,
407 the RPC fails with EINTR instead of restarting (thread_cancel).
409 *STATE_CHANGE is set nonzero if STATE->basic was modified and should
410 be applied back to the thread if it might ever run again, else zero. */
413 _hurdsig_abort_rpcs (struct hurd_sigstate
*ss
, int signo
, int sigthread
,
414 struct machine_thread_all_state
*state
, int *state_change
,
415 void (*reply
) (void))
417 extern const void _hurd_intr_rpc_msg_about_to
;
418 extern const void _hurd_intr_rpc_msg_in_trap
;
419 mach_port_t rcv_port
= MACH_PORT_NULL
;
420 mach_port_t intr_port
;
424 intr_port
= ss
->intr_port
;
425 if (intr_port
== MACH_PORT_NULL
)
426 /* No interruption needs done. */
427 return MACH_PORT_NULL
;
429 /* Abort the thread's kernel context, so any pending message send or
430 receive completes immediately or aborts. */
431 abort_thread (ss
, state
, reply
);
433 if (state
->basic
.PC
>= (natural_t
) &_hurd_intr_rpc_msg_about_to
434 && state
->basic
.PC
< (natural_t
) &_hurd_intr_rpc_msg_in_trap
)
436 /* The thread is about to do the RPC, but hasn't yet entered
437 mach_msg. Mutate the thread's state so it knows not to try
439 INTR_MSG_BACK_OUT (&state
->basic
);
440 MACHINE_THREAD_STATE_SET_PC (&state
->basic
,
441 &_hurd_intr_rpc_msg_in_trap
);
442 state
->basic
.SYSRETURN
= MACH_SEND_INTERRUPTED
;
445 else if (state
->basic
.PC
== (natural_t
) &_hurd_intr_rpc_msg_in_trap
446 /* The thread was blocked in the system call. After thread_abort,
447 the return value register indicates what state the RPC was in
449 && state
->basic
.SYSRETURN
== MACH_RCV_INTERRUPTED
)
451 /* The RPC request message was sent and the thread was waiting for
452 the reply message; now the message receive has been aborted, so
453 the mach_msg call will return MACH_RCV_INTERRUPTED. We must tell
454 the server to interrupt the pending operation. The thread must
455 wait for the reply message before running the signal handler (to
456 guarantee that the operation has finished being interrupted), so
457 our nonzero return tells the trampoline code to finish the message
458 receive operation before running the handler. */
460 mach_port_t
*reply
= interrupted_reply_port_location (ss
->thread
,
463 error_t err
= __interrupt_operation (intr_port
, _hurdsig_interrupt_timeout
);
469 /* The interrupt didn't work.
470 Destroy the receive right the thread is blocked on. */
471 __mach_port_destroy (__mach_task_self (), *reply
);
472 *reply
= MACH_PORT_NULL
;
475 /* The system call return value register now contains
476 MACH_RCV_INTERRUPTED; when mach_msg resumes, it will retry the
477 call. Since we have just destroyed the receive right, the
478 retry will fail with MACH_RCV_INVALID_NAME. Instead, just
479 change the return value here to EINTR so mach_msg will not
480 retry and the EINTR error code will propagate up. */
481 state
->basic
.SYSRETURN
= EINTR
;
487 /* All threads whose RPCs were interrupted by the interrupt_operation
488 call above will retry their RPCs unless we clear SS->intr_port.
489 So we clear it for the thread taking a signal when SA_RESTART is
490 clear, so that its call returns EINTR. */
491 if (! signo
|| !(_hurd_sigstate_actions (ss
) [signo
].sa_flags
& SA_RESTART
))
492 ss
->intr_port
= MACH_PORT_NULL
;
499 /* Abort the RPCs being run by all threads but this one;
500 all other threads should be suspended. If LIVE is nonzero, those
501 threads may run again, so they should be adjusted as necessary to be
502 happy when resumed. STATE is clobbered as a scratch area; its initial
503 contents are ignored, and its contents on return are not useful. */
506 abort_all_rpcs (int signo
, struct machine_thread_all_state
*state
, int live
)
508 /* We can just loop over the sigstates. Any thread doing something
509 interruptible must have one. We needn't bother locking because all
510 other threads are stopped. */
512 struct hurd_sigstate
*ss
;
514 mach_port_t
*reply_ports
;
516 /* First loop over the sigstates to count them.
517 We need to know how big a vector we will need for REPLY_PORTS. */
519 for (ss
= _hurd_sigstates
; ss
!= NULL
; ss
= ss
->next
)
522 reply_ports
= alloca (nthreads
* sizeof *reply_ports
);
525 for (ss
= _hurd_sigstates
; ss
!= NULL
; ss
= ss
->next
, ++nthreads
)
526 if (ss
->thread
== _hurd_msgport_thread
)
527 reply_ports
[nthreads
] = MACH_PORT_NULL
;
531 state
->set
= 0; /* Reset scratch area. */
533 /* Abort any operation in progress with interrupt_operation.
534 Record the reply port the thread is waiting on.
535 We will wait for all the replies below. */
536 reply_ports
[nthreads
] = _hurdsig_abort_rpcs (ss
, signo
, 1,
537 state
, &state_changed
,
541 if (reply_ports
[nthreads
] != MACH_PORT_NULL
)
543 /* We will wait for the reply to this RPC below, so the
544 thread must issue a new RPC rather than waiting for the
545 reply to the one it sent. */
546 state
->basic
.SYSRETURN
= EINTR
;
550 /* Aborting the RPC needed to change this thread's state,
551 and it might ever run again. So write back its state. */
552 __thread_set_state (ss
->thread
, MACHINE_THREAD_STATE_FLAVOR
,
553 (natural_t
*) &state
->basic
,
554 MACHINE_THREAD_STATE_COUNT
);
558 /* Wait for replies from all the successfully interrupted RPCs. */
559 while (nthreads
-- > 0)
560 if (reply_ports
[nthreads
] != MACH_PORT_NULL
)
563 mach_msg_header_t head
;
564 err
= __mach_msg (&head
, MACH_RCV_MSG
|MACH_RCV_TIMEOUT
, 0, sizeof head
,
565 reply_ports
[nthreads
],
566 _hurd_interrupted_rpc_timeout
, MACH_PORT_NULL
);
569 case MACH_RCV_TIMED_OUT
:
570 case MACH_RCV_TOO_LARGE
:
579 /* Wake up any sigsuspend or pselect call that is blocking SS->thread. SS must
582 wake_sigsuspend (struct hurd_sigstate
*ss
)
585 mach_msg_header_t msg
;
587 if (ss
->suspended
== MACH_PORT_NULL
)
590 /* There is a sigsuspend waiting. Tell it to wake up. */
591 msg
.msgh_bits
= MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND
, 0);
592 msg
.msgh_remote_port
= ss
->suspended
;
593 msg
.msgh_local_port
= MACH_PORT_NULL
;
594 /* These values do not matter. */
595 msg
.msgh_id
= 8675309; /* Jenny, Jenny. */
596 ss
->suspended
= MACH_PORT_NULL
;
597 err
= __mach_msg (&msg
, MACH_SEND_MSG
, sizeof msg
, 0,
598 MACH_PORT_NULL
, MACH_MSG_TIMEOUT_NONE
,
603 struct hurd_signal_preemptor
*_hurdsig_preemptors
= 0;
604 sigset_t _hurdsig_preempted_set
;
606 /* XXX temporary to deal with spelling fix */
607 weak_alias (_hurdsig_preemptors
, _hurdsig_preempters
)
609 /* Mask of stop signals. */
610 #define STOPSIGS (__sigmask (SIGTTIN) | __sigmask (SIGTTOU) \
611 | __sigmask (SIGSTOP) | __sigmask (SIGTSTP))
613 /* Actual delivery of a single signal. Called with SS unlocked. When
614 the signal is delivered, return SS, locked (or, if SS was originally
615 _hurd_global_sigstate, the sigstate of the actual thread the signal
616 was delivered to). If the signal is being traced, return NULL with
618 static struct hurd_sigstate
*
619 post_signal (struct hurd_sigstate
*ss
,
620 int signo
, struct hurd_signal_detail
*detail
,
621 int untraced
, void (*reply
) (void))
623 struct machine_thread_all_state thread_state
;
624 enum { stop
, ignore
, core
, term
, handle
} act
;
627 /* sigaction for preemptors */
628 struct sigaction preempt_sigaction
= {
629 .sa_flags
= SA_RESTART
632 struct sigaction
*action
;
634 /* Mark the signal as pending. */
635 void mark_pending (void)
637 __sigaddset (&ss
->pending
, signo
);
638 /* Save the details to be given to the handler when SIGNO is
640 ss
->pending_data
[signo
] = *detail
;
643 /* Suspend the process with SIGNO. */
646 /* Stop all other threads and mark ourselves stopped. */
649 /* Hold the siglock while stopping other threads to be
650 sure it is not held by another thread afterwards. */
651 __mutex_lock (&_hurd_siglock
);
652 __proc_dostop (port
, _hurd_msgport_thread
);
653 __mutex_unlock (&_hurd_siglock
);
654 abort_all_rpcs (signo
, &thread_state
, 1);
656 __proc_mark_stop (port
, signo
, detail
->code
);
660 /* Resume the process after a suspension. */
663 /* Resume the process from being stopped. */
665 mach_msg_type_number_t nthreads
, i
;
671 /* Tell the proc server we are continuing. */
672 __USEPORT (PROC
, __proc_mark_cont (port
));
673 /* Fetch ports to all our threads and resume them. */
674 err
= __task_threads (__mach_task_self (), &threads
, &nthreads
);
676 for (i
= 0; i
< nthreads
; ++i
)
678 if (act
== handle
&& threads
[i
] == ss
->thread
)
680 /* The thread that will run the handler is kept suspended. */
683 else if (threads
[i
] != _hurd_msgport_thread
)
685 err
= __thread_resume (threads
[i
]);
688 err
= __mach_port_deallocate (__mach_task_self (),
692 __vm_deallocate (__mach_task_self (),
693 (vm_address_t
) threads
,
694 nthreads
* sizeof *threads
);
699 sighandler_t handler
;
705 /* This is PTRACE_CONTINUE. */
710 /* This call is just to check for pending signals. */
711 _hurd_sigstate_lock (ss
);
715 thread_state
.set
= 0; /* We know nothing. */
717 _hurd_sigstate_lock (ss
);
719 /* If this is a global signal, try to find a thread ready to accept
720 it right away. This is especially important for untraced signals,
721 since going through the global pending mask would de-untrace them. */
722 if (ss
->thread
== MACH_PORT_NULL
)
724 struct hurd_sigstate
*rss
;
726 __mutex_lock (&_hurd_siglock
);
727 for (rss
= _hurd_sigstates
; rss
!= NULL
; rss
= rss
->next
)
729 if (! sigstate_is_global_rcv (rss
))
732 /* The global sigstate is already locked. */
733 __spin_lock (&rss
->lock
);
734 if (! __sigismember (&rss
->blocked
, signo
))
739 __spin_unlock (&rss
->lock
);
741 __mutex_unlock (&_hurd_siglock
);
744 /* We want the preemptors to be able to update the blocking mask
745 without affecting the delivery of this signal, so we save the
746 current value to test against later. */
747 sigset_t blocked
= ss
->blocked
;
749 /* Check for a preempted signal. Preempted signals can arrive during
750 critical sections. */
752 inline sighandler_t
try_preemptor (struct hurd_signal_preemptor
*pe
)
753 { /* PE cannot be null. */
756 if (HURD_PREEMPT_SIGNAL_P (pe
, signo
, detail
->exc_subcode
))
760 sighandler_t handler
= (*pe
->preemptor
) (pe
, ss
,
762 if (handler
!= SIG_ERR
)
773 handler
= ss
->preemptors
? try_preemptor (ss
->preemptors
) : SIG_ERR
;
775 /* If no thread-specific preemptor, check for a global one. */
776 if (handler
== SIG_ERR
&& __sigismember (&_hurdsig_preempted_set
, signo
))
778 __mutex_lock (&_hurd_siglock
);
779 handler
= try_preemptor (_hurdsig_preemptors
);
780 __mutex_unlock (&_hurd_siglock
);
786 if (handler
== SIG_IGN
)
787 /* Ignore the signal altogether. */
789 else if (handler
!= SIG_ERR
)
791 /* Run the preemption-provided handler. */
792 action
= &preempt_sigaction
;
797 /* No preemption. Do normal handling. */
799 action
= & _hurd_sigstate_actions (ss
) [signo
];
801 if (!untraced
&& __sigismember (&_hurdsig_traced
, signo
))
803 /* We are being traced. Stop to tell the debugger of the signal. */
805 /* Already stopped. Mark the signal as pending;
806 when resumed, we will notice it and stop again. */
810 _hurd_sigstate_unlock (ss
);
815 handler
= action
->sa_handler
;
817 if (handler
== SIG_DFL
)
818 /* Figure out the default action for this signal. */
822 /* A sig_post msg with SIGNO==0 is sent to
823 tell us to check for pending signals. */
855 if (_hurd_pgrp
== _hurd_pid
)
857 /* We are the process group leader. Since there is no
858 user-specified handler for SIGINFO, we use a default one
859 which prints something interesting. We use the normal
860 handler mechanism instead of just doing it here to avoid
861 the signal thread faulting or blocking in this
862 potentially hairy operation. */
864 handler
= _hurd_siginfo_handler
;
874 else if (handler
== SIG_IGN
)
879 if (__sigmask (signo
) & STOPSIGS
)
880 /* Stop signals clear a pending SIGCONT even if they
881 are handled or ignored (but not if preempted). */
882 __sigdelset (&ss
->pending
, SIGCONT
);
885 if (signo
== SIGCONT
)
886 /* Even if handled or ignored (but not preempted), SIGCONT clears
887 stop signals and resumes the process. */
888 ss
->pending
&= ~STOPSIGS
;
890 if (_hurd_stopped
&& act
!= stop
&& (untraced
|| signo
== SIGCONT
))
895 if (_hurd_orphaned
&& act
== stop
896 && (__sigmask (signo
) & (__sigmask (SIGTTIN
) | __sigmask (SIGTTOU
)
897 | __sigmask (SIGTSTP
))))
899 /* If we would ordinarily stop for a job control signal, but we are
900 orphaned so noone would ever notice and continue us again, we just
901 quietly die, alone and in the dark. */
902 detail
->code
= signo
;
907 /* Handle receipt of a blocked signal, or any signal while stopped. */
908 if (__sigismember (&blocked
, signo
) || (signo
!= SIGKILL
&& _hurd_stopped
))
914 /* Perform the chosen action for the signal. */
920 /* We are already stopped, but receiving an untraced stop
921 signal. Instead of resuming and suspending again, just
922 notify the proc server of the new stop signal. */
923 error_t err
= __USEPORT (PROC
, __proc_mark_stop
924 (port
, signo
, detail
->code
));
928 /* Suspend the process. */
934 /* Blocking or ignoring a machine exception is fatal.
935 Otherwise we could just spin on the faulting instruction. */
938 /* Nobody cares about this signal. If there was a call to resume
939 above in SIGCONT processing and we've left a thread suspended,
940 now's the time to set it going. */
943 assert (ss
->thread
!= MACH_PORT_NULL
);
944 err
= __thread_resume (ss
->thread
);
951 /* We got a fault setting up the stack frame for the handler.
952 Nothing to do but die; BSD gets SIGILL in this case. */
953 detail
->code
= signo
; /* XXX ? */
960 case term
: /* Time to die. */
961 case core
: /* And leave a rotting corpse. */
962 /* Have the proc server stop all other threads in our task. */
963 err
= __USEPORT (PROC
, __proc_dostop (port
, _hurd_msgport_thread
));
965 /* No more user instructions will be executed.
966 The signal can now be considered delivered. */
968 /* Abort all server operations now in progress. */
969 abort_all_rpcs (signo
, &thread_state
, 0);
972 int status
= W_EXITCODE (0, signo
);
973 /* Do a core dump if desired. Only set the wait status bit saying we
974 in fact dumped core if the operation was actually successful. */
975 if (act
== core
&& write_corefile (signo
, detail
))
977 /* Tell proc how we died and then stick the saber in the gut. */
983 /* Call a handler for this signal. */
985 struct sigcontext
*scp
, ocontext
;
986 int wait_for_reply
, state_changed
;
988 assert (ss
->thread
!= MACH_PORT_NULL
);
990 /* Stop the thread and abort its pending RPC operations. */
993 err
= __thread_suspend (ss
->thread
);
997 /* Abort the thread's kernel context, so any pending message send
998 or receive completes immediately or aborts. If an interruptible
999 RPC is in progress, abort_rpcs will do this. But we must always
1000 do it before fetching the thread's state, because
1001 thread_get_state is never kosher before thread_abort. */
1002 abort_thread (ss
, &thread_state
, NULL
);
1006 /* We have a previous sigcontext that sigreturn was about
1007 to restore when another signal arrived. */
1011 if (_hurdsig_catch_memory_fault (ss
->context
))
1013 /* We faulted reading the thread's stack. Forget that
1014 context and pretend it wasn't there. It almost
1015 certainly crash if this handler returns, but that's it's
1021 /* Copy the context from the thread's stack before
1022 we start diddling the stack to set up the handler. */
1023 ocontext
= *ss
->context
;
1024 ss
->context
= &ocontext
;
1026 _hurdsig_end_catch_fault ();
1028 if (! machine_get_basic_state (ss
->thread
, &thread_state
))
1030 loc
= interrupted_reply_port_location (ss
->thread
,
1032 if (loc
&& *loc
!= MACH_PORT_NULL
)
1033 /* This is the reply port for the context which called
1034 sigreturn. Since we are abandoning that context entirely
1035 and restoring SS->context instead, destroy this port. */
1036 __mach_port_destroy (__mach_task_self (), *loc
);
1038 /* The thread was in sigreturn, not in any interruptible RPC. */
1041 assert (! __spin_lock_locked (&ss
->critical_section_lock
));
1045 int crit
= __spin_lock_locked (&ss
->critical_section_lock
);
1048 = (_hurdsig_abort_rpcs (ss
,
1049 /* In a critical section, any RPC
1050 should be cancelled instead of
1051 restarted, regardless of
1052 SA_RESTART, so the entire
1053 "atomic" operation can be aborted
1055 crit
? 0 : signo
, 1,
1056 &thread_state
, &state_changed
,
1062 /* The thread is in a critical section. Mark the signal as
1063 pending. When it finishes the critical section, it will
1064 check for pending signals. */
1067 /* Some cases of interrupting an RPC must change the
1068 thread state to back out the call. Normally this
1069 change is rolled into the warping to the handler and
1070 sigreturn, but we are not running the handler now
1071 because the thread is in a critical section. Instead,
1072 mutate the thread right away for the RPC interruption
1073 and resume it; the RPC will return early so the
1074 critical section can end soon. */
1075 __thread_set_state (ss
->thread
, MACHINE_THREAD_STATE_FLAVOR
,
1076 (natural_t
*) &thread_state
.basic
,
1077 MACHINE_THREAD_STATE_COUNT
);
1079 ss
->intr_port
= MACH_PORT_NULL
;
1080 __thread_resume (ss
->thread
);
1085 /* Call the machine-dependent function to set the thread up
1086 to run the signal handler, and preserve its old context. */
1087 scp
= _hurd_setup_sighandler (ss
, action
, handler
, signo
, detail
,
1088 wait_for_reply
, &thread_state
);
1092 /* Set the machine-independent parts of the signal context. */
1095 /* Fetch the thread variable for the MiG reply port,
1096 and set it to MACH_PORT_NULL. */
1097 mach_port_t
*loc
= interrupted_reply_port_location (ss
->thread
,
1102 scp
->sc_reply_port
= *loc
;
1103 *loc
= MACH_PORT_NULL
;
1106 scp
->sc_reply_port
= MACH_PORT_NULL
;
1108 /* Save the intr_port in use by the interrupted code,
1109 and clear the cell before running the trampoline. */
1110 scp
->sc_intr_port
= ss
->intr_port
;
1111 ss
->intr_port
= MACH_PORT_NULL
;
1115 /* After the handler runs we will restore to the state in
1116 SS->context, not the state of the thread now. So restore
1117 that context's reply port and intr port. */
1119 scp
->sc_reply_port
= ss
->context
->sc_reply_port
;
1120 scp
->sc_intr_port
= ss
->context
->sc_intr_port
;
1126 /* Backdoor extra argument to signal handler. */
1127 scp
->sc_error
= detail
->error
;
1129 /* Block requested signals while running the handler. */
1130 scp
->sc_mask
= ss
->blocked
;
1131 __sigorset (&ss
->blocked
, &ss
->blocked
, &action
->sa_mask
);
1133 /* Also block SIGNO unless we're asked not to. */
1134 if (! (action
->sa_flags
& (SA_RESETHAND
| SA_NODEFER
)))
1135 __sigaddset (&ss
->blocked
, signo
);
1137 /* Reset to SIG_DFL if requested. SIGILL and SIGTRAP cannot
1138 be automatically reset when delivered; the system silently
1139 enforces this restriction. */
1140 if (action
->sa_flags
& SA_RESETHAND
1141 && signo
!= SIGILL
&& signo
!= SIGTRAP
)
1142 action
->sa_handler
= SIG_DFL
;
1144 /* Any sigsuspend call must return after the handler does. */
1145 wake_sigsuspend (ss
);
1147 /* Start the thread running the handler (or possibly waiting for an
1148 RPC reply before running the handler). */
1149 err
= __thread_set_state (ss
->thread
, MACHINE_THREAD_STATE_FLAVOR
,
1150 (natural_t
*) &thread_state
.basic
,
1151 MACHINE_THREAD_STATE_COUNT
);
1152 assert_perror (err
);
1153 err
= __thread_resume (ss
->thread
);
1154 assert_perror (err
);
1155 thread_state
.set
= 0; /* Everything we know is now wrong. */
1163 /* Return the set of pending signals in SS which should be delivered. */
1165 pending_signals (struct hurd_sigstate
*ss
)
1167 /* We don't worry about any pending signals if we are stopped, nor if
1168 SS is in a critical section. We are guaranteed to get a sig_post
1169 message before any of them become deliverable: either the SIGCONT
1170 signal, or a sig_post with SIGNO==0 as an explicit poll when the
1171 thread finishes its critical section. */
1172 if (_hurd_stopped
|| __spin_lock_locked (&ss
->critical_section_lock
))
1175 return _hurd_sigstate_pending (ss
) & ~ss
->blocked
;
1178 /* Post the specified pending signals in SS and return 1. If one of
1179 them is traced, abort immediately and return 0. SS must be locked on
1180 entry and will be unlocked in all cases. */
1182 post_pending (struct hurd_sigstate
*ss
, sigset_t pending
, void (*reply
) (void))
1185 struct hurd_signal_detail detail
;
1187 /* Make sure SS corresponds to an actual thread, since we assume it won't
1188 change in post_signal. */
1189 assert (ss
->thread
!= MACH_PORT_NULL
);
1191 for (signo
= 1; signo
< NSIG
; ++signo
)
1192 if (__sigismember (&pending
, signo
))
1194 detail
= sigstate_clear_pending (ss
, signo
);
1195 _hurd_sigstate_unlock (ss
);
1197 /* Will reacquire the lock, except if the signal is traced. */
1198 if (! post_signal (ss
, signo
, &detail
, 0, reply
))
1202 /* No more signals pending; SS->lock is still locked. */
1203 _hurd_sigstate_unlock (ss
);
1208 /* Post all the pending signals of all threads and return 1. If a traced
1209 signal is encountered, abort immediately and return 0. */
1211 post_all_pending_signals (void (*reply
) (void))
1213 struct hurd_sigstate
*ss
;
1214 sigset_t pending
= 0;
1218 __mutex_lock (&_hurd_siglock
);
1219 for (ss
= _hurd_sigstates
; ss
!= NULL
; ss
= ss
->next
)
1221 _hurd_sigstate_lock (ss
);
1223 pending
= pending_signals (ss
);
1225 /* post_pending() below will unlock SS. */
1228 _hurd_sigstate_unlock (ss
);
1230 __mutex_unlock (&_hurd_siglock
);
1234 if (! post_pending (ss
, pending
, reply
))
1239 /* Deliver a signal. SS is not locked. */
1241 _hurd_internal_post_signal (struct hurd_sigstate
*ss
,
1242 int signo
, struct hurd_signal_detail
*detail
,
1243 mach_port_t reply_port
,
1244 mach_msg_type_name_t reply_port_type
,
1247 /* Reply to this sig_post message. */
1248 __typeof (__msg_sig_post_reply
) *reply_rpc
1249 = (untraced
? __msg_sig_post_untraced_reply
: __msg_sig_post_reply
);
1253 if (reply_port
== MACH_PORT_NULL
)
1255 err
= (*reply_rpc
) (reply_port
, reply_port_type
, 0);
1256 reply_port
= MACH_PORT_NULL
;
1257 if (err
!= MACH_SEND_INVALID_DEST
) /* Ignore dead reply port. */
1258 assert_perror (err
);
1261 ss
= post_signal (ss
, signo
, detail
, untraced
, reply
);
1265 /* The signal was neither fatal nor traced. We still hold SS->lock. */
1266 if (signo
!= 0 && ss
->thread
!= MACH_PORT_NULL
)
1268 /* The signal has either been ignored or is now being handled. We can
1269 consider it delivered and reply to the killer. */
1272 /* Post any pending signals for this thread. */
1273 if (! post_pending (ss
, pending_signals (ss
), reply
))
1278 /* If this was a process-wide signal or a poll request, we need
1279 to check for pending signals for all threads. */
1280 _hurd_sigstate_unlock (ss
);
1281 if (! post_all_pending_signals (reply
))
1284 /* All pending signals delivered to all threads.
1285 Now we can send the reply message even for signal 0. */
1290 /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
1291 Returns zero if so, otherwise the error code to return to the sender. */
1294 signal_allowed (int signo
, mach_port_t refport
)
1296 if (signo
< 0 || signo
>= NSIG
)
1299 if (refport
== __mach_task_self ())
1300 /* Can send any signal. */
1303 /* Avoid needing to check for this below. */
1304 if (refport
== MACH_PORT_NULL
)
1317 /* Job control signals can be sent by the controlling terminal. */
1318 if (__USEPORT (CTTYID
, port
== refport
))
1324 /* A continue signal can be sent by anyone in the session. */
1325 mach_port_t sessport
;
1326 if (! __USEPORT (PROC
, __proc_getsidport (port
, &sessport
)))
1328 __mach_port_deallocate (__mach_task_self (), sessport
);
1329 if (refport
== sessport
)
1338 /* Any io object a file descriptor refers to might send us
1339 one of these signals using its async ID port for REFPORT.
1341 This is pretty wide open; it is not unlikely that some random
1342 process can at least open for reading something we have open,
1343 get its async ID port, and send us a spurious SIGIO or SIGURG
1344 signal. But BSD is actually wider open than that!--you can set
1345 the owner of an io object to any process or process group
1346 whatsoever and send them gratuitous signals.
1348 Someday we could implement some reasonable scheme for
1349 authorizing SIGIO and SIGURG signals properly. */
1352 int lucky
= 0; /* True if we find a match for REFPORT. */
1353 __mutex_lock (&_hurd_dtable_lock
);
1354 for (d
= 0; !lucky
&& (unsigned) d
< (unsigned) _hurd_dtablesize
; ++d
)
1356 struct hurd_userlink ulink
;
1358 mach_port_t asyncid
;
1359 if (_hurd_dtable
[d
] == NULL
)
1361 port
= _hurd_port_get (&_hurd_dtable
[d
]->port
, &ulink
);
1362 if (! __io_get_icky_async_id (port
, &asyncid
))
1364 if (refport
== asyncid
)
1365 /* Break out of the loop on the next iteration. */
1367 __mach_port_deallocate (__mach_task_self (), asyncid
);
1369 _hurd_port_free (&_hurd_dtable
[d
]->port
, &ulink
, port
);
1371 __mutex_unlock (&_hurd_dtable_lock
);
1372 /* If we found a lucky winner, we've set D to -1 in the loop. */
1378 /* If this signal is legit, we have done `goto win' by now.
1379 When we return the error, mig deallocates REFPORT. */
1383 /* Deallocate the REFPORT send right; we are done with it. */
1384 __mach_port_deallocate (__mach_task_self (), refport
);
1389 /* Implement the sig_post RPC from <hurd/msg.defs>;
1390 sent when someone wants us to get a signal. */
1392 _S_msg_sig_post (mach_port_t me
,
1393 mach_port_t reply_port
, mach_msg_type_name_t reply_port_type
,
1394 int signo
, natural_t sigcode
,
1395 mach_port_t refport
)
1398 struct hurd_signal_detail d
;
1400 if (err
= signal_allowed (signo
, refport
))
1403 d
.code
= d
.exc_subcode
= sigcode
;
1406 /* Post the signal to a global receiver thread (or mark it pending in
1407 the global sigstate). This will reply when the signal can be
1408 considered delivered. */
1409 _hurd_internal_post_signal (_hurd_global_sigstate
,
1410 signo
, &d
, reply_port
, reply_port_type
,
1411 0); /* Stop if traced. */
1413 return MIG_NO_REPLY
; /* Already replied. */
1416 /* Implement the sig_post_untraced RPC from <hurd/msg.defs>;
1417 sent when the debugger wants us to really get a signal
1418 even if we are traced. */
1420 _S_msg_sig_post_untraced (mach_port_t me
,
1421 mach_port_t reply_port
,
1422 mach_msg_type_name_t reply_port_type
,
1423 int signo
, natural_t sigcode
,
1424 mach_port_t refport
)
1427 struct hurd_signal_detail d
;
1429 if (err
= signal_allowed (signo
, refport
))
1432 d
.code
= d
.exc_subcode
= sigcode
;
1435 /* Post the signal to the designated signal-receiving thread. This will
1436 reply when the signal can be considered delivered. */
1437 _hurd_internal_post_signal (_hurd_global_sigstate
,
1438 signo
, &d
, reply_port
, reply_port_type
,
1439 1); /* Untraced flag. */
1441 return MIG_NO_REPLY
; /* Already replied. */
1444 extern void __mig_init (void *);
1446 #include <mach/task_special_ports.h>
1448 /* Initialize the message port, _hurd_global_sigstate, and start the
1452 _hurdsig_init (const int *intarray
, size_t intarraysize
)
1455 vm_size_t stacksize
;
1456 struct hurd_sigstate
*ss
;
1458 __mutex_init (&_hurd_siglock
);
1460 err
= __mach_port_allocate (__mach_task_self (),
1461 MACH_PORT_RIGHT_RECEIVE
,
1463 assert_perror (err
);
1465 /* Make a send right to the signal port. */
1466 err
= __mach_port_insert_right (__mach_task_self (),
1469 MACH_MSG_TYPE_MAKE_SEND
);
1470 assert_perror (err
);
1472 /* Initialize the global signal state. */
1473 _hurd_global_sigstate
= _hurd_thread_sigstate (MACH_PORT_NULL
);
1475 /* We block all signals, and let actual threads pull them from the
1477 __sigfillset(& _hurd_global_sigstate
->blocked
);
1479 /* Initialize the main thread's signal state. */
1480 ss
= _hurd_self_sigstate ();
1482 /* Mark it as a process-wide signal receiver. Threads in this set use
1483 the common action vector in _hurd_global_sigstate. */
1484 _hurd_sigstate_set_global_rcv (ss
);
1486 /* Copy inherited signal settings from our parent (or pre-exec process
1488 if (intarraysize
> INIT_SIGMASK
)
1489 ss
->blocked
= intarray
[INIT_SIGMASK
];
1490 if (intarraysize
> INIT_SIGPENDING
)
1491 _hurd_global_sigstate
->pending
= intarray
[INIT_SIGPENDING
];
1492 if (intarraysize
> INIT_SIGIGN
&& intarray
[INIT_SIGIGN
] != 0)
1495 for (signo
= 1; signo
< NSIG
; ++signo
)
1496 if (intarray
[INIT_SIGIGN
] & __sigmask(signo
))
1497 _hurd_global_sigstate
->actions
[signo
].sa_handler
= SIG_IGN
;
1500 /* Start the signal thread listening on the message port. */
1502 #pragma weak __pthread_create
1503 if (!__pthread_create
)
1505 err
= __thread_create (__mach_task_self (), &_hurd_msgport_thread
);
1506 assert_perror (err
);
1508 stacksize
= __vm_page_size
* 8; /* Small stack for signal thread. */
1509 err
= __mach_setup_thread (__mach_task_self (), _hurd_msgport_thread
,
1510 _hurd_msgport_receive
,
1511 (vm_address_t
*) &__hurd_sigthread_stack_base
,
1513 assert_perror (err
);
1514 err
= __mach_setup_tls (_hurd_msgport_thread
);
1515 assert_perror (err
);
1517 __hurd_sigthread_stack_end
= __hurd_sigthread_stack_base
+ stacksize
;
1519 /* Reinitialize the MiG support routines so they will use a per-thread
1520 variable for the cached reply port. */
1521 __mig_init ((void *) __hurd_sigthread_stack_base
);
1523 err
= __thread_resume (_hurd_msgport_thread
);
1524 assert_perror (err
);
1529 pthread_attr_t attr
;
1533 /* When pthread is being used, we need to make the signal thread a
1534 proper pthread. Otherwise it cannot use mutex_lock et al, which
1535 will be the pthread versions. Various of the message port RPC
1536 handlers need to take locks, so we need to be able to call into
1537 pthread code and meet its assumptions about how our thread and
1538 its stack are arranged. Since pthread puts it there anyway,
1539 we'll let the signal thread's per-thread variables be found as for
1540 any normal pthread, and just leave the magic __hurd_sigthread_*
1541 values all zero so they'll be ignored. */
1543 #pragma weak __pthread_detach
1544 #pragma weak __pthread_getattr_np
1545 #pragma weak __pthread_attr_getstack
1546 __pthread_create(&thread
, NULL
, &_hurd_msgport_receive
, NULL
);
1548 /* Record signal thread stack layout for fork() */
1549 __pthread_getattr_np (thread
, &attr
);
1550 __pthread_attr_getstack (&attr
, &addr
, &size
);
1551 __hurd_sigthread_stack_base
= (uintptr_t) addr
;
1552 __hurd_sigthread_stack_end
= __hurd_sigthread_stack_base
+ size
;
1554 __pthread_detach(thread
);
1556 /* XXX We need the thread port for the signal thread further on
1557 in this thread (see hurdfault.c:_hurdsigfault_init).
1558 Therefore we block until _hurd_msgport_thread is initialized
1559 by the newly created thread. This really shouldn't be
1560 necessary; we should be able to fetch the thread port for a
1561 pthread from here. */
1562 while (_hurd_msgport_thread
== 0)
1566 /* Receive exceptions on the signal port. */
1567 #ifdef TASK_EXCEPTION_PORT
1568 __task_set_special_port (__mach_task_self (),
1569 TASK_EXCEPTION_PORT
, _hurd_msgport
);
1570 #elif defined (EXC_MASK_ALL)
1571 __task_set_exception_ports (__mach_task_self (),
1572 EXC_MASK_ALL
& ~(EXC_MASK_SYSCALL
1573 | EXC_MASK_MACH_SYSCALL
1574 | EXC_MASK_RPC_ALERT
),
1576 EXCEPTION_DEFAULT
, MACHINE_THREAD_STATE
);
1578 # error task_set_exception_port?
1581 /* Sanity check. Any pending, unblocked signals should have been
1582 taken by our predecessor incarnation (i.e. parent or pre-exec state)
1583 before packing up our init ints. This assert is last (not above)
1584 so that signal handling is all set up to handle the abort. */
1585 assert ((ss
->pending
&~ ss
->blocked
) == 0);
1588 /* Reauthenticate with the proc server. */
1591 reauth_proc (mach_port_t
new)
1593 mach_port_t ref
, ignore
;
1595 ref
= __mach_reply_port ();
1596 if (! HURD_PORT_USE (&_hurd_ports
[INIT_PORT_PROC
],
1597 __proc_reauthenticate (port
, ref
,
1598 MACH_MSG_TYPE_MAKE_SEND
)
1599 || __auth_user_authenticate (new, ref
,
1600 MACH_MSG_TYPE_MAKE_SEND
,
1602 && ignore
!= MACH_PORT_NULL
)
1603 __mach_port_deallocate (__mach_task_self (), ignore
);
1604 __mach_port_destroy (__mach_task_self (), ref
);
1606 /* Set the owner of the process here too. */
1607 __mutex_lock (&_hurd_id
.lock
);
1608 if (!_hurd_check_ids ())
1609 HURD_PORT_USE (&_hurd_ports
[INIT_PORT_PROC
],
1610 __proc_setowner (port
,
1612 ? _hurd_id
.gen
.uids
[0] : 0),
1613 !_hurd_id
.gen
.nuids
));
1614 __mutex_unlock (&_hurd_id
.lock
);
1616 (void) &reauth_proc
; /* Silence compiler warning. */
1618 text_set_element (_hurd_reauth_hook
, reauth_proc
);
1620 /* Like `getenv', but safe for the signal thread to run.
1621 If the environment is trashed, this will just return NULL. */
1624 _hurdsig_getenv (const char *variable
)
1626 if (__libc_enable_secure
)
1629 if (_hurdsig_catch_memory_fault (__environ
))
1630 /* We bombed in getenv. */
1634 const size_t len
= strlen (variable
);
1636 char *volatile *ep
= __environ
;
1639 const char *p
= *ep
;
1640 _hurdsig_fault_preemptor
.first
= (long int) p
;
1641 _hurdsig_fault_preemptor
.last
= VM_MAX_ADDRESS
;
1642 if (! strncmp (p
, variable
, len
) && p
[len
] == '=')
1646 valuelen
= strlen (p
);
1647 _hurdsig_fault_preemptor
.last
= (long int) (p
+ valuelen
);
1648 value
= malloc (++valuelen
);
1650 memcpy (value
, p
, valuelen
);
1653 _hurdsig_fault_preemptor
.first
= (long int) ++ep
;
1654 _hurdsig_fault_preemptor
.last
= (long int) (ep
+ 1);
1656 _hurdsig_end_catch_fault ();