From 6df1b2474adfc23c9cfff5a4496108bea0c37511 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Thu, 4 Jan 1996 00:06:01 +0000 Subject: Rewritten. --- hurd/hurdsig.c | 54 ++++++++++++++++++++++-------------------- sysdeps/generic/strsep.c | 26 +++++++++++--------- sysdeps/mach/hurd/fork.c | 22 +++++++++++++++-- sysdeps/mach/hurd/jmp-unwind.c | 6 ++--- sysdeps/mach/hurd/setgid.c | 27 ++++++++++----------- 5 files changed, 78 insertions(+), 57 deletions(-) diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c index cecc415574..290dba825e 100644 --- a/hurd/hurdsig.c +++ b/hurd/hurdsig.c @@ -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 #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); + + /* Check for a preempted signal. Preempted signals can arrive during + critical sections. */ - 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); + 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. */ diff --git a/sysdeps/generic/strsep.c b/sysdeps/generic/strsep.c index bb4d68bd6e..b57a22f649 100644 --- a/sysdeps/generic/strsep.c +++ b/sysdeps/generic/strsep.c @@ -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 #include 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; } diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c index 25279645ee..6fadb3d97d 100644 --- a/sysdeps/mach/hurd/fork.c +++ b/sysdeps/mach/hurd/fork.c @@ -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); } diff --git a/sysdeps/mach/hurd/jmp-unwind.c b/sysdeps/mach/hurd/jmp-unwind.c index 822501f8e5..20ca5f8aa6 100644 --- a/sysdeps/mach/hurd/jmp-unwind.c +++ b/sysdeps/mach/hurd/jmp-unwind.c @@ -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 -#include #include +#include +#include #include @@ -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. */ diff --git a/sysdeps/mach/hurd/setgid.c b/sysdeps/mach/hurd/setgid.c index b2d9313307..ca493a4f7b 100644 --- a/sysdeps/mach/hurd/setgid.c +++ b/sysdeps/mach/hurd/setgid.c @@ -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); -- cgit v1.2.3