Sun Apr 2 13:13:52 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>

* sysdeps/mach/hurd/i386/trampoline.c: Add a link to
 	SS->active_resources, so that _hurdsig_longjmp_from_handler will
 	be called when a longjmp unwinds the signal frame.
	* sysdeps/mach/hurd/i386/sigreturn.c: Remove the link on the
 	SS->active_resources chain added by _hurd_setup_sighandler.
	* hurd/sigunwind.c: New file.
	* hurd/Makefile (sig): Add sigunwind.

	* Makerules (lib%.so: lib%_pic.a): Remove dir name from $*.

	* MakeTAGS (tags-sources): Include $(all-dist).
	[subdir] (all-dist): Define to $(distribute).
This commit is contained in:
Roland McGrath 1995-04-02 22:08:59 +00:00
parent 193ce8dcd6
commit e607b492e5
7 changed files with 183 additions and 5 deletions

View File

@ -1,3 +1,18 @@
Sun Apr 2 13:13:52 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* sysdeps/mach/hurd/i386/trampoline.c: Add a link to
SS->active_resources, so that _hurdsig_longjmp_from_handler will
be called when a longjmp unwinds the signal frame.
* sysdeps/mach/hurd/i386/sigreturn.c: Remove the link on the
SS->active_resources chain added by _hurd_setup_sighandler.
* hurd/sigunwind.c: New file.
* hurd/Makefile (sig): Add sigunwind.
* Makerules (lib%.so: lib%_pic.a): Remove dir name from $*.
* MakeTAGS (tags-sources): Include $(all-dist).
[subdir] (all-dist): Define to $(distribute).
Sat Apr 1 00:08:06 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
* Makerules (lib%.so: lib%_pic.a): Pass -L options for subdir and

View File

@ -1,6 +1,6 @@
# Make the TAGS files.
# Copyright (C) 1992, 1994 Free Software Foundation, Inc.
# Copyright (C) 1992, 1994, 1995 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
@ -33,9 +33,9 @@ ifeq ($(subdir),ctype)
# the header files so tags for optimizing #define's in the
# headers won't be put in the tags files, but for ctype,
# the functions are just backup for the #define's in the header.
tags_sources = $(all-headers) $(all-sources)
tags_sources = $(all-headers) $(all-sources) $(all-dist)
else # Not ctype.
tags_sources = $(all-sources) $(all-headers)
tags_sources = $(all-sources) $(all-headers) $(all-dist)
endif # ctype
endif # No tags_sources
@ -67,6 +67,8 @@ all-dist = $(foreach Dist,$(wildcard $(all-dirs:%=%/Dist)),\
$(filter %.c %.h %.S %.s,\
$(shell cat $(Dist)))))
tags_sources = $(all-sources) $(all-headers) $(all-dist)
else
all-dist = $(distribute)
endif
# All different versions of $(sources), preserving the configured sysdep

View File

@ -343,7 +343,7 @@ ifeq (yes,$(build-shared))
lib%.so: lib%_pic.a
$(LINK.o) -shared -o $@ -Wl,--whole-archive $< \
-L$(firstword $(objdir) .) -L$(common-objpfx:%/=%) \
$(LDLIBS-$*.so)
$(LDLIBS-$(notdir $*).so)
endif
libobjs: $(foreach o,$(object-suffixes),\

View File

@ -51,7 +51,7 @@ routines = hurdinit hurdid hurdlookup hurdpid hurdrlimit hurdprio hurdexec \
ports-get ports-set hurdports hurdmsg \
$(sig) $(dtable) hurdinline port-cleanup
sig = hurdsig hurdfault faultexc siginfo hurd-raise preempt-sig \
trampoline longjmp-ts catch-exc exc2signal hurdkill
trampoline longjmp-ts catch-exc exc2signal hurdkill sigunwind
dtable = dtable port2fd new-fd alloc-fd intern-fd \
getdport openport \
fd-close fd-read fd-write hurdioctl ctty-input ctty-output

135
hurd/sigunwind.c Normal file
View File

@ -0,0 +1,135 @@
/* longjmp cleanup function for unwinding past signal handlers.
Copyright (C) 1995 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.h>
#include "thread_state.h"
#include <setjmp.h>
#include <assert.h>
extern void _hurd_longjmp_thread_state (struct machine_thread_state *,
jmp_buf env, int value);
/* _hurd_setup_sighandler puts a link on the `active resources' chain so that
_longjmp_unwind will call this function with the `struct sigcontext *'
describing the context interrupted by the signal, when `longjmp' is jumping
to an environment that unwinds past the interrupted frame. */
void
_hurdsig_longjmp_from_handler (void *data, jmp_buf env, int val)
{
struct sigcontext *scp = data;
struct hurd_sigstate *ss = _hurd_self_sigstate ();
int onstack;
inline void cleanup (void)
{
/* Destroy the MiG reply port used by the signal handler, and restore
the reply port in use by the thread when interrupted. */
mach_port_t *reply_port =
(mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
if (*reply_port)
__mach_port_destroy (__mach_task_self (), *reply_port);
*reply_port = scp->sc_reply_port;
}
__spin_lock (&ss->lock);
/* We should only ever be called from _longjmp_unwind (in jmp-unwind.c),
which calls us inside a critical section. */
assert (ss->critical_section);
/* Are we on the alternate signal stack now? */
onstack = (ss->sigaltstack.ss_flags & SA_ONSTACK);
__spin_unlock (&ss->lock);
if (onstack && ! scp->sc_onstack)
{
/* We are unwinding off the signal stack. We must use sigreturn to
do it robustly. Mutate the sigcontext so that when sigreturn
resumes from that context, it will be as if `__longjmp (ENV, VAL)'
were done. */
struct hurd_userlink *link;
/* Continue _longjmp_unwind's job of running the unwind
forms for frames being unwound, since we will not
return to its loop like this one, which called us. */
for (link = ss->active_resources;
link && _JMPBUF_UNWINDS (env[0].__jmpbuf, link);
link = link->thread.next)
if (_hurd_userlink_unlink (link))
{
if (link->cleanup == &_hurdsig_longjmp_from_handler)
{
/* We are unwinding past another signal handler invocation.
Just finish the cleanup for this (inner) one, and then
swap SCP to restore to the outer context. */
cleanup ();
scp = link->cleanup_data;
}
else
(*link->cleanup) (link->cleanup_data, env, val);
}
#define sc_machine_thread_state paste(sc_,machine_thread_state)
#define paste(a,b) paste1(a,b)
#define paste1(a,b) a##b
/* There are no more unwind forms to be run!
Now we can just have the sigreturn do the longjmp for us. */
_hurd_longjmp_thread_state
((struct machine_thread_state *) &scp->sc_machine_thread_state,
env, val);
/* Restore to the same current signal mask. If sigsetjmp saved the
mask, longjmp has already restored it as desired; if not, we
should leave it as it is. */
scp->sc_mask = ss->blocked;
/* sigreturn expects the link added by _hurd_setup_sighandler
to still be there, but _longjmp_unwind removed it just before
calling us. Put it back now so sigreturn can find it. */
link = (void *) &scp[1];
assert (! link->resource.next && ! link->resource.prevp);
assert (link->thread.next == ss->active_resources);
assert (link->thread.prevp = &ss->active_resources);
if (link->thread.next)
link->thread.next->thread.prevp = &link->thread.next;
ss->active_resources = link;
/* We must momentarily exit the critical section so that sigreturn
does not get upset with us. But we don't want signal handlers
running right now, because we are presently in the bogus state of
having run all the unwind forms back to ENV's frame, but our SP is
still inside those unwound frames. */
__spin_lock (&ss->lock);
ss->critical_section = 0;
ss->blocked = ~(sigset_t) 0 & ~_SIG_CANT_MASK;
__spin_unlock (&ss->lock);
/* Restore to the modified signal context that now
performs `longjmp (ENV, VAL)'. */
__sigreturn (scp);
assert (! "sigreturn returned!");
}
/* We are not unwinding off the alternate signal stack. So nothing
really funny is going on here. We can just clean up this handler
frame and let _longjmp_unwind continue unwinding. */
cleanup ();
ss->intr_port = scp->sc_intr_port;
}

View File

@ -28,6 +28,7 @@ int
__sigreturn (struct sigcontext *scp)
{
struct hurd_sigstate *ss;
struct hurd_userlink *link = (void *) &scp[1];
mach_port_t *reply_port;
if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))
@ -39,6 +40,11 @@ __sigreturn (struct sigcontext *scp)
ss = _hurd_self_sigstate ();
__spin_lock (&ss->lock);
/* Remove the link on the `active resources' chain added by
_hurd_setup_sighandler. Its purpose was to make sure
that we got called; now we have, it is done. */
_hurd_userlink_unlink (link);
/* Restore the set of blocked signals, and the intr_port slot. */
ss->blocked = scp->sc_mask;
ss->intr_port = scp->sc_intr_port;

View File

@ -18,6 +18,7 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <hurd/signal.h>
#include <hurd/userlink.h>
#include "thread_state.h"
#include <assert.h>
#include <errno.h>
@ -55,6 +56,7 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
void *sigreturn_returns_here;
struct sigcontext *return_scp; /* Same; arg to sigreturn. */
struct sigcontext ctx;
struct hurd_userlink link;
} *stackframe;
if (ss->context)
@ -118,6 +120,24 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
{
int ok;
extern void _hurdsig_longjmp_from_handler (void *, jmp_buf, int);
/* Add a link to the thread's active-resources list. We mark this as
the only user of the "resource", so the cleanup function will be
called by any longjmp which is unwinding past the signal frame.
The cleanup function (in sigunwind.c) will make sure that all the
appropriate cleanups done by sigreturn are taken care of. */
stackframe->link.cleanup = &_hurdsig_longjmp_from_handler;
stackframe->link.cleanup_data = &stackframe->ctx;
stackframe->link.resource.next = NULL;
stackframe->link.resource.prevp = NULL;
stackframe->link.thread.next = ss->active_resources;
stackframe->link.thread.prevp = &ss->active_resources;
if (stackframe->link.thread.next)
stackframe->link.thread.next->thread.prevp
= &stackframe->link.thread.next;
ss->active_resources = &stackframe->link;
/* Set up the arguments for the signal handler. */
stackframe->signo = signo;
stackframe->sigcode = sigcode;