Rewritten.

This commit is contained in:
Roland McGrath 1996-01-04 00:06:01 +00:00
parent 71733723fb
commit 6df1b2474a
5 changed files with 78 additions and 57 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
/* Copyright (C) 1991, 92, 93, 94, 95, 96 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
@ -74,10 +74,11 @@ _hurd_thread_sigstate (thread_t thread)
ss->thread = thread;
__spin_lock_init (&ss->lock);
/* Initialze default state. */
/* Initialize default state. */
__sigemptyset (&ss->blocked);
__sigemptyset (&ss->pending);
memset (&ss->sigaltstack, 0, sizeof (ss->sigaltstack));
ss->preempters = NULL;
ss->suspended = 0;
ss->intr_port = MACH_PORT_NULL;
ss->context = NULL;
@ -231,6 +232,7 @@ interrupted_reply_port_location (struct machine_thread_all_state *thread_state,
return portloc;
}
#include <hurd/sigpreempt.h>
#include "intr-msg.h"
/* SS->thread is suspended.
@ -404,9 +406,8 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
}
}
struct hurd_signal_preempt *_hurd_signal_preempt[NSIG];
struct mutex _hurd_signal_preempt_lock;
struct hurd_signal_preempter *_hurdsig_preempters;
sigset_t _hurdsig_preempted_set;
/* Mask of stop signals. */
#define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
@ -423,9 +424,8 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
error_t err;
struct machine_thread_all_state thread_state;
enum { stop, ignore, core, term, handle } act;
struct hurd_signal_preempter *pe;
sighandler_t handler;
struct hurd_signal_preempt *pe;
sighandler_t (*preempt) (thread_t, int, long int, int) = NULL;
sigset_t pending;
int ss_suspended;
@ -521,35 +521,37 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
thread_state.set = 0; /* We know nothing. */
/* Check for a preempted signal. Preempted signals
can arrive during critical sections. */
__mutex_lock (&_hurd_signal_preempt_lock);
for (pe = _hurd_signal_preempt[signo]; pe != NULL; pe = pe->next)
if (pe->handler && sigcode >= pe->first && sigcode <= pe->last)
{
preempt = pe->handler;
break;
}
__mutex_unlock (&_hurd_signal_preempt_lock);
__spin_lock (&ss->lock);
handler = SIG_DFL;
if (preempt)
/* Let the preempting handler examine the thread.
If it returns SIG_DFL, we run the normal handler;
otherwise we use the handler it returns. */
handler = (*preempt) (ss->thread, signo, sigcode, sigerror);
/* Check for a preempted signal. Preempted signals can arrive during
critical sections. */
handler = SIG_ERR;
for (pe = ss->preempters; pe && handler == SIG_ERR; pe = pe->next)
if (HURD_PREEMPT_SIGNAL_P (pe, signo, sigcode))
handler = (*pe->preempter) (pe, ss, &signo, &sigcode, &sigerror);
if (handler == SIG_ERR && (__sigmask (signo) & _hurdsig_preempted_set))
{
__mutex_lock (&_hurd_siglock);
for (pe = _hurdsig_preempters; pe && handler == SIG_ERR; pe = pe->next)
if (HURD_PREEMPT_SIGNAL_P (pe, signo, sigcode))
handler = (*pe->preempter) (pe, ss, &signo, &sigcode, &sigerror);
__mutex_unlock (&_hurd_siglock);
}
ss_suspended = 0;
if (handler != SIG_DFL)
if (handler == SIG_IGN)
/* Ignore the signal altogether. */
act = ignore;
if (handler != SIG_ERR)
/* Run the preemption-provided handler. */
act = handle;
else
{
/* No preemption. Do normal handling. */
__spin_lock (&ss->lock);
if (!untraced && (_hurd_exec_flags & EXEC_TRACED))
{
/* We are being traced. Stop to tell the debugger of the signal. */

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
/* Copyright (C) 1992, 1993, 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
@ -16,24 +16,28 @@ 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 <ansidecl.h>
#include <string.h>
char *
DEFUN(strsep, (stringp, delim),
char **stringp AND CONST char *delim)
strsep (char **stringp, const char *delim)
{
char *begin, *end;
begin = *stringp + strspn (*stringp, delim);
end = *stringp + strcspn (*stringp, delim);
if (end == *stringp)
begin = *stringp;
if (! begin || *begin == '\0')
return NULL;
if (*end != '\0')
*end++ = '\0';
*stringp = end;
/* Find the end of the token. */
end = strpbrk (begin, delim);
if (end)
{
/* Terminate the token and advance *STRINGP past the delimiters. */
*end++ = '\0';
*stringp = end + strspn (end, delim);
}
else
/* No more delimiters; this is the last token. */
*stringp = NULL;
return begin;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
/* Copyright (C) 1994, 1995, 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
@ -121,7 +121,6 @@ __fork (void)
__spin_lock (&_hurd_ports[i].lock);
ports_locked = 1;
*(volatile task_t *) &__mach_task_self_; /* XXX work around kernel bug */
/* Stop all other threads while copying the address space,
so nothing changes. */
@ -130,6 +129,25 @@ __fork (void)
{
stopped = 1;
#define XXX_KERNEL_PAGE_FAULT_BUG /* XXX work around page fault bug in mk */
#ifdef XXX_KERNEL_PAGE_FAULT_BUG
/* Gag me with a pitchfork.
The bug scenario is this:
- The page containing __mach_task_self_ is paged out.
- The signal thread was faulting on that page when we
suspended it via proc_dostop. It holds some lock, or set
some busy bit, or somesuch.
- Now this thread faults on that same page.
- GRATUIOUS DEADLOCK
We can break the deadlock by aborting the thread that faulted
first, which if the bug happened was the signal thread because
it is the only other thread and we just suspended it.
*/
__thread_abort (_hurd_msgport_thread);
#endif
/* Create the child task. It will inherit a copy of our memory. */
err = __task_create (__mach_task_self (), 1, &newtask);
}

View File

@ -1,5 +1,5 @@
/* _longjmp_unwind -- Clean up stack frames unwound by longjmp. Hurd version.
Copyright (C) 1995 Free Software Foundation, Inc.
Copyright (C) 1995, 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
@ -18,8 +18,9 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <setjmp.h>
#include <hurd/signal.h>
#include <hurd/userlink.h>
#include <hurd/signal.h>
#include <hurd/sigpreempt.h>
#include <assert.h>
@ -36,7 +37,6 @@ _longjmp_unwind (jmp_buf env, int val)
{
struct hurd_sigstate *ss = _hurd_self_sigstate ();
struct hurd_userlink *link;
struct hurd_signal_preempter **p;
/* All access to SS->active_resources must take place inside a critical
section where signal handlers cannot run. */

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
/* Copyright (C) 1991, 92, 93, 94, 95, 96 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
@ -46,21 +46,26 @@ DEFUN(__setgid, (gid), gid_t gid)
gid_t *newgen, *newaux, auxbuf[2];
size_t ngen, naux;
newaux = _hurd_id.aux.gids;
naux = _hurd_id.aux.ngids;
if (_hurd_id.gen.ngids == 0)
{
/* No effective gids now. The new set will be just GID. */
newgen = &gid;
ngen = 1;
}
else if (_hurd_id.gen.gids[0] == 0)
else
{
/* We are root; set the effective, real, and saved to GID. */
_hurd_id.gen.gids[0] = gid;
_hurd_id.valid = 0;
newgen = _hurd_id.gen.gids;
ngen = _hurd_id.gen.ngids;
}
newaux = _hurd_id.aux.gids;
naux = _hurd_id.aux.ngids;
if (_hurd_id.gen.nuids > 0 && _hurd_id.gen.uids[0] == 0)
{
/* We are root; set the real and saved IDs too. */
_hurd_id.valid = 0;
if (_hurd_id.aux.ngids < 2)
{
newaux = auxbuf;
@ -68,20 +73,12 @@ DEFUN(__setgid, (gid), gid_t gid)
}
newaux[0] = newaux[1] = gid;
}
else
{
/* We are not root; just change the effective GID. */
_hurd_id.gen.gids[0] = gid;
_hurd_id.valid = 0;
newgen = _hurd_id.gen.gids;
ngen = _hurd_id.gen.ngids;
}
err = __USEPORT (AUTH, __auth_makeauth
(port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
_hurd_id.gen.uids, _hurd_id.gen.nuids,
_hurd_id.aux.uids, _hurd_id.aux.nuids,
newgen, ngen, newaux, naux,
_hurd_id.gen.gids, _hurd_id.gen.ngids,
_hurd_id.aux.gids, _hurd_id.aux.ngids,
&newauth));
}
__mutex_unlock (&_hurd_id.lock);