]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Sun Apr 2 13:13:52 1995 Roland McGrath <roland@churchy.gnu.ai.mit.edu>
authorRoland McGrath <roland@gnu.org>
Sun, 2 Apr 1995 22:08:59 +0000 (22:08 +0000)
committerRoland McGrath <roland@gnu.org>
Sun, 2 Apr 1995 22:08:59 +0000 (22:08 +0000)
* 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).

ChangeLog
MakeTAGS
Makerules
hurd/Makefile
hurd/sigunwind.c [new file with mode: 0644]
sysdeps/mach/hurd/i386/sigreturn.c
sysdeps/mach/hurd/i386/trampoline.c

index 4b5fb9bcdc29c55bcd2415a27cabd7264b07c353..1f6e98a6b64278e682ce38d03d851c2c930c7c0e 100644 (file)
--- 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
index acea142bf6c7af0f912d8fd1260cdd5b55538ae9..29dfc47f014da6de64e440bda34c4c3d25c641fc 100644 (file)
--- 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
index f3fdb37c2fe031398e745bea6c7f717811e16cc4..55e7520c642889dc0edf5ca2215087cbfe42ae1c 100644 (file)
--- 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),\
index 278d8ec31545f93c93683a6ecdbb4eb9c60152ea..254e89cb5068634cd377cabe9a102ac3687eed45 100644 (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
diff --git a/hurd/sigunwind.c b/hurd/sigunwind.c
new file mode 100644 (file)
index 0000000..7420f43
--- /dev/null
@@ -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;
+}
index 19ba1d472c03fdea37754ddc741f01ff5b762e77..d00fa7755fab8341e94a7827a194a542f00fb166 100644 (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;
index a83a8a8e7dd63c4f43974b371d3f6611e2b43627..5f3361b97e965fda7b9a5ead932293426975da3f 100644 (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;