summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>1995-04-02 22:08:59 +0000
committerRoland McGrath <roland@gnu.org>1995-04-02 22:08:59 +0000
commite607b492e56e2fc3c08e72d5a58349354a584cf2 (patch)
tree8e48c89250656dd4322f32248c3d5497ae148951
parent193ce8dcd6c1eea5c68e6d4d8db2002c0085925b (diff)
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).
-rw-r--r--ChangeLog15
-rw-r--r--MakeTAGS8
-rw-r--r--Makerules2
-rw-r--r--hurd/Makefile2
-rw-r--r--hurd/sigunwind.c135
-rw-r--r--sysdeps/mach/hurd/i386/sigreturn.c6
-rw-r--r--sysdeps/mach/hurd/i386/trampoline.c20
7 files changed, 183 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 4b5fb9bcdc..1f6e98a6b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/MakeTAGS b/MakeTAGS
index acea142bf6..29dfc47f01 100644
--- a/MakeTAGS
+++ b/MakeTAGS
@@ -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
diff --git a/Makerules b/Makerules
index f3fdb37c2f..55e7520c64 100644
--- a/Makerules
+++ b/Makerules
@@ -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),\
diff --git a/hurd/Makefile b/hurd/Makefile
index 278d8ec315..254e89cb50 100644
--- a/hurd/Makefile
+++ b/hurd/Makefile
@@ -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
diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c
new file mode 100644
index 0000000000..7420f43ae4
--- /dev/null
+++ b/hurd/sigunwind.c
@@ -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;
+}
diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
index 19ba1d472c..d00fa7755f 100644
--- a/sysdeps/mach/hurd/i386/sigreturn.c
+++ b/sysdeps/mach/hurd/i386/sigreturn.c
@@ -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;
diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
index a83a8a8e7d..5f3361b97e 100644
--- a/sysdeps/mach/hurd/i386/trampoline.c
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -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;