Wed Jan 3 20:23:42 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>

* hurd/catch-signal.c: New file.

	* hurd/intr-msg.c: When restarting RPC, fetch a new reply port.

	* hurd/hurdsig.c: Use new hurdfault.h interface.
	(abort_all_rpcs): Mutate return value to EINTR in threads whose
	replies we will wait for.

	* hurd/hurdkill.c (_hurd_sig_post): When doing pgrp, make sure we
	do ourselves last.

Wed Jan  3 19:17:10 1996  Miles Bader  <miles@gnu.ai.mit.edu>

	* sysdeps/mach/hurd/access.c (__access): Put the uid/gid arguments
	to auth_makeauth() in the right order.

Wed Jan  3 17:19:04 1996  Roland McGrath  <roland@churchy.gnu.ai.mit.edu>

	* sysdeps/generic/strsep.c: Rewritten.

	* sysdeps/mach/hurd/fork.c: Use a different workaround for the
 	suspended page fault deadlock kernel bug: thread_abort our signal
 	thread first thing after proc_dostop.

	* sysdeps/mach/hurd/setgid.c: Rewrote gid frobnication to
	recognize rootness properly.

	* hurd/hurdsig.c: Use new signal preemption interface.
This commit is contained in:
Roland McGrath 1996-01-04 10:00:22 +00:00
parent 67f27f3a02
commit fb8e70d6dd
4 changed files with 185 additions and 33 deletions

View File

@ -1,3 +1,32 @@
Wed Jan 3 20:23:42 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* hurd/catch-signal.c: New file.
* hurd/intr-msg.c: When restarting RPC, fetch a new reply port.
* hurd/hurdsig.c: Use new hurdfault.h interface.
(abort_all_rpcs): Mutate return value to EINTR in threads whose
replies we will wait for.
* hurd/hurdkill.c (_hurd_sig_post): When doing pgrp, make sure we
do ourselves last.
Wed Jan 3 19:17:10 1996 Miles Bader <miles@gnu.ai.mit.edu>
* sysdeps/mach/hurd/access.c (__access): Put the uid/gid arguments
to auth_makeauth() in the right order.
Wed Jan 3 17:19:04 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* sysdeps/generic/strsep.c: Rewritten.
* sysdeps/mach/hurd/fork.c: Use a different workaround for the
suspended page fault deadlock kernel bug: thread_abort our signal
thread first thing after proc_dostop.
* sysdeps/mach/hurd/setgid.c: Rewrote gid frobnication to
recognize rootness properly.
Tue Jan 2 00:50:10 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu> Tue Jan 2 00:50:10 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* hurd/hurd/signal.h (struct hurd_sigstate): New member `preempters'. * hurd/hurd/signal.h (struct hurd_sigstate): New member `preempters'.
@ -6,6 +35,7 @@ Tue Jan 2 00:50:10 1996 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* hurd/preempt-sig.c: Rewritten with new interface. * hurd/preempt-sig.c: Rewritten with new interface.
* sysdeps/mach/hurd/jmp-unwind.c (_longjmp_unwind): Remove local signal * sysdeps/mach/hurd/jmp-unwind.c (_longjmp_unwind): Remove local signal
preempters being unwound past. preempters being unwound past.
* hurd/hurdsig.c: Use new signal preemption interface.
* db: New directory, 4.4 BSD db package incorporated from BSD db-1.85 * db: New directory, 4.4 BSD db package incorporated from BSD db-1.85
release. release.

87
hurd/catch-signal.c Normal file
View File

@ -0,0 +1,87 @@
/* Convenience function to catch expected signals during an operation.
Copyright (C) 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <hurd/signal.h>
#include <hurd/sigpreempt.h>
#include <string.h>
#include <assert.h>
error_t
hurd_catch_signal (sigset_t sigset,
unsigned long int first, unsigned long int last,
error_t (*operate) (struct hurd_signal_preempter *),
sighandler_t handler)
{
jmp_buf buf;
void throw (int signo, long int sigcode, struct sigcontext *scp)
{ longjmp (buf, scp->sc_error ?: EGRATUITOUS); }
struct hurd_signal_preempter preempter =
{
sigset, first, last,
NULL, handler == SIG_ERR ? (sighandler_t) &throw : handler,
};
struct hurd_sigstate *const ss = _hurd_self_sigstate ();
error_t error;
if (handler == SIG_ERR)
/* Not our handler; don't bother saving state. */
error = 0;
else
/* This returns again with nonzero value when we preempt a signal. */
error = setjmp (buf);
if (error == 0)
{
/* Install a signal preempter for the thread. */
__spin_lock (&ss->lock);
preempter.next = ss->preempters;
ss->preempters = &preempter;
__spin_unlock (&ss->lock);
/* Try the operation that might crash. */
(*operate) (&preempter);
}
/* Either FUNCTION completed happily and ERROR is still zero, or it hit
an expected signal and `throw' made setjmp return the signal error
code in ERROR. Now we can remove the preempter and return. */
__spin_lock (&ss->lock);
assert (ss->preempters == &preempter);
ss->preempters = preempter.next;
__spin_unlock (&ss->lock);
return error;
}
error_t
hurd_safe_memset (void *dest, int byte, size_t nbytes)
{
error_t operate (struct hurd_signal_preempter *preempter)
{
memset (dest, byte, nbytes);
return 0;
}
return hurd_catch_signal (sigmask (SIGBUS) | sigmask (SIGSEGV),
(vm_address_t) dest, (vm_address_t) dest + nbytes,
&operate, SIG_ERR);
}

View File

@ -121,8 +121,9 @@ _hurd_thread_sigstate (thread_t thread)
#include "thread_state.h" #include "thread_state.h"
#include <hurd/msg_server.h> #include <hurd/msg_server.h>
#include <hurd/msg_reply.h> /* For __msg_sig_post_reply. */ #include <hurd/msg_reply.h> /* For __msg_sig_post_reply. */
#include <assert.h>
#include <hurd/interrupt.h> #include <hurd/interrupt.h>
#include <assert.h>
#include <unistd.h>
int _hurd_core_limit; /* XXX */ int _hurd_core_limit; /* XXX */
@ -216,12 +217,9 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp mach_port_t *portloc = (mach_port_t *) __hurd_threadvar_location_from_sp
(_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP); (_HURD_THREADVAR_MIG_REPLY, (void *) thread_state->basic.SP);
if (sigthread && _hurdsig_catch_fault (SIGSEGV)) if (sigthread && _hurdsig_catch_memory_fault (portloc))
{ /* Faulted trying to read the stack. */
assert (_hurdsig_fault_sigcode == (long int) portloc); return NULL;
/* Faulted trying to read the stack. */
return NULL;
}
/* Fault now if this pointer is bogus. */ /* Fault now if this pointer is bogus. */
*(volatile mach_port_t *) portloc = *portloc; *(volatile mach_port_t *) portloc = *portloc;
@ -363,9 +361,9 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
reply_ports = alloca (nthreads * sizeof *reply_ports); reply_ports = alloca (nthreads * sizeof *reply_ports);
nthreads = 0; nthreads = 0;
for (ss = _hurd_sigstates; ss != NULL; ss = ss->next) for (ss = _hurd_sigstates; ss != NULL; ss = ss->next, ++nthreads)
if (ss->thread == _hurd_msgport_thread) if (ss->thread == _hurd_msgport_thread)
reply_ports[nthreads++] = MACH_PORT_NULL; reply_ports[nthreads] = MACH_PORT_NULL;
else else
{ {
int state_changed; int state_changed;
@ -374,15 +372,26 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
/* Abort any operation in progress with interrupt_operation. /* Abort any operation in progress with interrupt_operation.
Record the reply port the thread is waiting on. Record the reply port the thread is waiting on.
We will wait for all the replies below. */ We will wait for all the replies below. */
reply_ports[nthreads++] = _hurdsig_abort_rpcs (ss, signo, 1, reply_ports[nthreads] = _hurdsig_abort_rpcs (ss, signo, 1,
state, &state_changed, state, &state_changed,
NULL); NULL);
if (state_changed && live) if (live)
/* Aborting the RPC needed to change this thread's state, {
and it might ever run again. So write back its state. */ if (reply_ports[nthreads] != MACH_PORT_NULL)
__thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR, {
(natural_t *) &state->basic, /* We will wait for the reply to this RPC below, so the
MACHINE_THREAD_STATE_COUNT); thread must issue a new RPC rather than waiting for the
reply to the one it sent. */
state->basic.SYSRETURN = EINTR;
state_changed = 1;
}
if (state_changed)
/* Aborting the RPC needed to change this thread's state,
and it might ever run again. So write back its state. */
__thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
(natural_t *) &state->basic,
MACHINE_THREAD_STATE_COUNT);
}
} }
/* Wait for replies from all the successfully interrupted RPCs. */ /* Wait for replies from all the successfully interrupted RPCs. */
@ -744,10 +753,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
mach_port_t *loc; mach_port_t *loc;
if (_hurdsig_catch_fault (SIGSEGV)) if (_hurdsig_catch_memory_fault (ss->context))
{ {
assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
_hurdsig_fault_sigcode < (long int) (ss->context + 1));
/* We faulted reading the thread's stack. Forget that /* We faulted reading the thread's stack. Forget that
context and pretend it wasn't there. It almost context and pretend it wasn't there. It almost
certainly crash if this handler returns, but that's it's certainly crash if this handler returns, but that's it's
@ -1176,14 +1183,34 @@ text_set_element (_hurd_reauth_hook, reauth_proc);
const char * const char *
_hurdsig_getenv (const char *variable) _hurdsig_getenv (const char *variable)
{ {
if (_hurdsig_catch_fault (SIGSEGV)) if (_hurdsig_catch_memory_fault (__environ))
/* We bombed in getenv. */ /* We bombed in getenv. */
return NULL; return NULL;
else else
{ {
const char *value = getenv (variable); const size_t len = strlen (variable);
/* Fault now if VALUE is a bogus string. */ char *value = NULL;
(void) strlen (value); char *volatile *ep = __environ;
while (*ep)
{
const char *p = *ep;
_hurdsig_fault_preempter.first = (long int) p;
_hurdsig_fault_preempter.last = VM_MAX_ADDRESS;
if (! strncmp (p, variable, len) && p[len] == '=')
{
char *value;
size_t valuelen;
p += len + 1;
valuelen = strlen (p);
_hurdsig_fault_preempter.last = (long int) (p + valuelen);
value = malloc (++valuelen);
if (value)
memcpy (value, p, valuelen);
break;
}
_hurdsig_fault_preempter.first = (long int) ++ep;
_hurdsig_fault_preempter.last = (long int) (ep + 1);
}
_hurdsig_end_catch_fault (); _hurdsig_end_catch_fault ();
return value; return value;
} }

View File

@ -1,5 +1,5 @@
/* Replacement for mach_msg used in interruptible Hurd RPCs. /* Replacement for mach_msg used in interruptible Hurd RPCs.
Copyright (C) 1995 Free Software Foundation, Inc. Copyright (C) 1995, 1996 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -19,6 +19,7 @@ Cambridge, MA 02139, USA. */
#include <mach.h> #include <mach.h>
#include <mach/mig_errors.h> #include <mach/mig_errors.h>
#include <mach/mig_support.h>
#include <hurd/signal.h> #include <hurd/signal.h>
#include "intr-msg.h" #include "intr-msg.h"
@ -45,7 +46,7 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
return EINTR when some other thread gets a signal, in which case we return EINTR when some other thread gets a signal, in which case we
want to restart our call. */ want to restart our call. */
ss->intr_port = msg->msgh_remote_port; ss->intr_port = msg->msgh_remote_port;
/* A signal may arrive here, after intr_port is set, but before /* A signal may arrive here, after intr_port is set, but before
the mach_msg system call. The signal handler might do an the mach_msg system call. The signal handler might do an
interruptible RPC, and clobber intr_port; then it would not be interruptible RPC, and clobber intr_port; then it would not be
@ -58,12 +59,12 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
if (ss->cancel) if (ss->cancel)
{ {
err = EINTR;
ss->cancel = 0; ss->cancel = 0;
return EINTR;
} }
else
err = INTR_MSG_TRAP (msg, option, send_size, err = INTR_MSG_TRAP (msg, option, send_size,
rcv_size, rcv_name, timeout, notify); rcv_size, rcv_name, timeout, notify);
switch (err) switch (err)
{ {
@ -83,7 +84,14 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
signal thread will have cleared SS->intr_port. signal thread will have cleared SS->intr_port.
Since it's not cleared, the signal was for another thread, Since it's not cleared, the signal was for another thread,
or SA_RESTART is set. Restart the interrupted call. */ or SA_RESTART is set. Restart the interrupted call. */
goto message; {
restart:
if (rcv_name != MACH_PORT_NULL)
/* Make sure we have a valid reply port. The one we were using
may have been destroyed by interruption. */
msg->msgh_local_port = rcv_name = __mig_get_reply_port ();
goto message;
}
/* FALLTHROUGH */ /* FALLTHROUGH */
case MACH_RCV_PORT_DIED: case MACH_RCV_PORT_DIED:
@ -139,7 +147,7 @@ _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg,
if (ss->intr_port != MACH_PORT_NULL) if (ss->intr_port != MACH_PORT_NULL)
/* Nope; repeat the RPC. /* Nope; repeat the RPC.
XXX Resources moved? */ XXX Resources moved? */
goto message; goto restart;
else else
/* The EINTR return indicates cancellation, so clear the /* The EINTR return indicates cancellation, so clear the
flag. */ flag. */