[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH 2/2] patches/hurd-i386/submitted-hurdsig-*: Improve signals on Hurd



New symbols are introduced by
patches/hurd-i386/submitted-hurdsig-global-dispositions.diff, for which the
version GLIBC_2.13_DEBIAN_11 is used temporarily.  The plan is to create
aliases when these patches are merged upstream with the official one.
---
 debian/changelog                                   |    7 +
 debian/libc0.3.symbols.hurd-i386                   |    1 +
 .../hurd-i386/submitted-PTRACE_CONTINUE.diff       |   29 -
 .../hurd-i386/submitted-hurdsig-SA_SIGINFO.diff    |  527 +++++++++
 .../hurd-i386/submitted-hurdsig-fixes-2.diff       |   44 +
 .../patches/hurd-i386/submitted-hurdsig-fixes.diff |  352 ++++++
 .../submitted-hurdsig-global-dispositions.diff     | 1238 ++++++++++++++++++++
 debian/patches/series                              |    4 +-
 8 files changed, 2172 insertions(+), 30 deletions(-)
 delete mode 100644 debian/patches/hurd-i386/submitted-PTRACE_CONTINUE.diff
 create mode 100644 debian/patches/hurd-i386/submitted-hurdsig-SA_SIGINFO.diff
 create mode 100644 debian/patches/hurd-i386/submitted-hurdsig-fixes-2.diff
 create mode 100644 debian/patches/hurd-i386/submitted-hurdsig-fixes.diff
 create mode 100644 debian/patches/hurd-i386/submitted-hurdsig-global-dispositions.diff

diff --git a/debian/changelog b/debian/changelog
index 9ccce14..b0740b8 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -13,20 +13,27 @@ eglibc (2.13-11) UNRELEASED; urgency=low
     - uses upstream RFTSIGZMB for exit signal selection when available.
   * Disable multiarch support on amd64, kfreebsd-amd64, ppc64, sparc64 until
     we fix the /lib64 -> /lib symlink issue. Closes: #632176.
   * Reenable patches/any/cvs-resolv-different-nameserver.diff. Add 
     patches/any/submitted-resolv-assert.diff to fix assertion triggered by the
     previous patch.  Closes: #535504, #602291.
   * Add support for s390x.
 
   [ Jeremie Koenig ]
   * Add debian/libc0.3.symbols.hurd-i386.
+  * New patches to improve the signal code on Hurd:
+    patches/hurd-i386/submitted-hurdsig-fixes.diff,
+    patches/hurd-i386/submitted-hurdsig-global-dispositions.diff,
+    patches/hurd-i386/submitted-hurdsig-SA_SIGINFO.diff,
+    patches/hurd-i386/submitted-hurdsig-fixes-2.diff.
+  * Remove patches/hurd-i386/submitted-PTRACE_CONTINUE.diff, now covered by
+    submitted-hurdsig-fixes.diff.
 
  -- Aurelien Jarno <aurel32@debian.org>  Sun, 10 Jul 2011 22:01:11 +0200
 
 eglibc (2.13-10) unstable; urgency=low
 
   * control.in/main: tag libc-bin Essential: yes.
   * Revert patch to make libc6-dev multiarch.  Closes: #632667.
   * Add patches/alpha/submitted-statfs64.patch to fix statvfs() on alpha.
     Closes: #324051.
 
diff --git a/debian/libc0.3.symbols.hurd-i386 b/debian/libc0.3.symbols.hurd-i386
index 7c9977f..cde325a 100644
--- a/debian/libc0.3.symbols.hurd-i386
+++ b/debian/libc0.3.symbols.hurd-i386
@@ -1,15 +1,16 @@
 ld.so.1 #PACKAGE# #MINVER#
 #include "symbols.wildcards"
 libc.so.0.3 #PACKAGE# #MINVER#
 #include "symbols.wildcards"
  *@HURD_CTHREADS_0.3 2.11
+ *@GLIBC_2.13_DEBIAN_11 2.13-11~
 libBrokenLocale.so.1 #PACKAGE# #MINVER#
 #include "symbols.wildcards"
 libSegFault.so #PACKAGE# #MINVER#
  __invoke_dynamic_linker__@Base 2.3.6
 #include "symbols.wildcards"
 libcidn.so.1 #PACKAGE# #MINVER#
 #include "symbols.wildcards"
 libcrypt.so.1 #PACKAGE# #MINVER#
 #include "symbols.wildcards"
 libdl.so.2 #PACKAGE# #MINVER#
diff --git a/debian/patches/hurd-i386/submitted-PTRACE_CONTINUE.diff b/debian/patches/hurd-i386/submitted-PTRACE_CONTINUE.diff
deleted file mode 100644
index bcfd266..0000000
--- a/debian/patches/hurd-i386/submitted-PTRACE_CONTINUE.diff
+++ /dev/null
@@ -1,29 +0,0 @@
-http://sourceware.org/ml/libc-alpha/2011-06/msg00124.html
-
-* hurd/hurdsig.c (post_signal): Don't call resume() with ACT uninitialized,
-as it might result in the target thread being left suspended.
----
- hurd/hurdsig.c |    7 +++++--
- 1 files changed, 5 insertions(+), 2 deletions(-)
-
-diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
-index 0ec0f27..74a01a6 100644
---- a/hurd/hurdsig.c
-+++ b/hurd/hurdsig.c
-@@ -558,8 +558,11 @@ post_signal (struct hurd_sigstate *ss,
-   if (signo == 0)
-     {
-       if (untraced)
--	/* This is PTRACE_CONTINUE.  */
--	resume ();
-+	{
-+	  /* This is PTRACE_CONTINUE.  */
-+	  act = ignore;
-+	  resume ();
-+	}
- 
-       /* This call is just to check for pending signals.  */
-       __spin_lock (&ss->lock);
--- 
-1.7.5.3
-
diff --git a/debian/patches/hurd-i386/submitted-hurdsig-SA_SIGINFO.diff b/debian/patches/hurd-i386/submitted-hurdsig-SA_SIGINFO.diff
new file mode 100644
index 0000000..405c351
--- /dev/null
+++ b/debian/patches/hurd-i386/submitted-hurdsig-SA_SIGINFO.diff
@@ -0,0 +1,527 @@
+diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
+index 1c4733a..cc96f21 100644
+--- a/hurd/hurd/signal.h
++++ b/hurd/hurd/signal.h
+@@ -264,6 +264,11 @@ extern void _hurd_raise_signal (struct hurd_sigstate *ss, int signo,
+ extern void _hurd_exception2signal (struct hurd_signal_detail *detail,
+ 				    int *signo);
+ 
++/* Translate a Mach exception into a signal with a legacy sigcode.  */
++
++extern void _hurd_exception2signal_legacy (struct hurd_signal_detail *detail,
++					   int *signo);
++
+ 
+ /* Make the thread described by SS take the signal described by SIGNO and
+    DETAIL.  If the process is traced, this will in fact stop with a SIGNO
+diff --git a/hurd/hurdinit.c b/hurd/hurdinit.c
+index 259f8a3..97d3460 100644
+--- a/hurd/hurdinit.c
++++ b/hurd/hurdinit.c
+@@ -176,7 +176,7 @@ _hurd_new_proc_init (char **argv,
+     /* This process is "traced", meaning it should stop on signals or exec.
+        We are all set up now to handle signals.  Stop ourselves, to inform
+        our parent (presumably a debugger) that the exec has completed.  */
+-    __msg_sig_post (_hurd_msgport, SIGTRAP, 0, __mach_task_self ());
++    __msg_sig_post (_hurd_msgport, SIGTRAP, TRAP_TRACE, __mach_task_self ());
+ }
+ 
+ #include <shlib-compat.h>
+diff --git a/sysdeps/mach/hurd/bits/sigaction.h b/sysdeps/mach/hurd/bits/sigaction.h
+new file mode 100644
+index 0000000..4528b38
+--- /dev/null
++++ b/sysdeps/mach/hurd/bits/sigaction.h
+@@ -0,0 +1,79 @@
++/* Copyright (C) 1991,92,96,97,98,2001 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 Lesser General Public
++   License as published by the Free Software Foundation; either
++   version 2.1 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
++   Lesser General Public License for more details.
++
++   You should have received a copy of the GNU Lesser General Public
++   License along with the GNU C Library; if not, write to the Free
++   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
++   02111-1307 USA.  */
++
++#ifndef _SIGNAL_H
++# error "Never include <bits/sigaction.h> directly; use <signal.h> instead."
++#endif
++
++/* These definitions match those used by the 4.4 BSD kernel.
++   If the operating system has a `sigaction' system call that correctly
++   implements the POSIX.1 behavior, there should be a system-dependent
++   version of this file that defines `struct sigaction' and the `SA_*'
++   constants appropriately.  */
++
++/* Structure describing the action to be taken when a signal arrives.  */
++struct sigaction
++  {
++    /* Signal handler.  */
++#ifdef __USE_POSIX199309
++    union
++      {
++	/* Used if SA_SIGINFO is not set.  */
++	__sighandler_t sa_handler;
++	/* Used if SA_SIGINFO is set.  */
++	void (*sa_sigaction) (int, siginfo_t *, void *);
++      }
++    __sigaction_handler;
++# define sa_handler	__sigaction_handler.sa_handler
++# define sa_sigaction	__sigaction_handler.sa_sigaction
++#else
++    __sighandler_t sa_handler;
++#endif
++
++    /* Additional set of signals to be blocked.  */
++    __sigset_t sa_mask;
++
++    /* Special flags.  */
++    int sa_flags;
++  };
++
++/* Bits in `sa_flags'.  */
++#if defined __USE_UNIX98 || defined __USE_MISC
++# define SA_ONSTACK	0x0001	/* Take signal on signal stack.  */
++# define SA_RESTART	0x0002	/* Restart syscall on signal return.  */
++# define SA_NODEFER	0x0010	/* Don't automatically block the signal when
++				    its handler is being executed.  */
++# define SA_RESETHAND	0x0004	/* Reset to SIG_DFL on entry to handler.  */
++# define SA_SIGINFO	0x0040	/* Signal handler with SA_SIGINFO args */
++#endif
++#define	SA_NOCLDSTOP	0x0008	/* Don't send SIGCHLD when children stop.  */
++
++#ifdef __USE_MISC
++# define SA_INTERRUPT	0	/* Historical no-op ("not SA_RESTART").  */
++
++/* Some aliases for the SA_ constants.  */
++# define SA_NOMASK    SA_NODEFER
++# define SA_ONESHOT   SA_RESETHAND
++# define SA_STACK     SA_ONSTACK
++#endif
++
++
++/* Values for the HOW argument to `sigprocmask'.  */
++#define	SIG_BLOCK	1	/* Block signals.  */
++#define	SIG_UNBLOCK	2	/* Unblock signals.  */
++#define	SIG_SETMASK	3	/* Set the set of blocked signals.  */
+diff --git a/sysdeps/mach/hurd/i386/bits/sigcontext.h b/sysdeps/mach/hurd/i386/bits/sigcontext.h
+index a78dd2f..1956d41 100644
+--- a/sysdeps/mach/hurd/i386/bits/sigcontext.h
++++ b/sysdeps/mach/hurd/i386/bits/sigcontext.h
+@@ -96,6 +96,10 @@ struct sigcontext
+ #define sc_ps	sc_efl
+ 
+ 
++/* The deprecated sigcode values below are passed as an extra, non-portable
++   argument to regular signal handlers.  You should use SA_SIGINFO handlers
++   instead, which use the standard POSIX signal codes.  */
++
+ /* Codes for SIGFPE.  */
+ #define FPE_INTOVF_TRAP		0x1 /* integer overflow */
+ #define FPE_INTDIV_FAULT	0x2 /* integer divide by zero */
+diff --git a/sysdeps/mach/hurd/i386/exc2signal.c b/sysdeps/mach/hurd/i386/exc2signal.c
+index a6bf750..7ffeb5f 100644
+--- a/sysdeps/mach/hurd/i386/exc2signal.c
++++ b/sysdeps/mach/hurd/i386/exc2signal.c
+@@ -24,8 +24,8 @@
+ /* Translate the Mach exception codes, as received in an `exception_raise' RPC,
+    into a signal number and signal subcode.  */
+ 
+-void
+-_hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
++static void
++exception2signal (struct hurd_signal_detail *detail, int *signo, int posix)
+ {
+   detail->error = 0;
+ 
+@@ -37,44 +37,62 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+       break;
+ 
+     case EXC_BAD_ACCESS:
+-      if (detail->exc_code == KERN_INVALID_ADDRESS
+-	  || detail->exc_code == KERN_PROTECTION_FAILURE
+-	  || detail->exc_code == KERN_WRITE_PROTECTION_FAILURE)
+-	*signo = SIGSEGV;
+-      else
+-	*signo = SIGBUS;
+-      detail->code = detail->exc_subcode;
++      switch (detail->exc_code)
++        {
++	case KERN_INVALID_ADDRESS:
++	case KERN_MEMORY_FAILURE:
++	  *signo = SIGSEGV;
++	  detail->code = posix ? SEGV_MAPERR : detail->exc_subcode;
++	  break;
++
++	case KERN_PROTECTION_FAILURE:
++	case KERN_WRITE_PROTECTION_FAILURE:
++	  *signo = SIGSEGV;
++	  detail->code = posix ? SEGV_ACCERR : detail->exc_subcode;
++	  break;
++
++	default:
++	  *signo = SIGBUS;
++	  detail->code = 0;
++	  break;
++	}
+       detail->error = detail->exc_code;
+       break;
+ 
+     case EXC_BAD_INSTRUCTION:
+       *signo = SIGILL;
+-      if (detail->exc_code == EXC_I386_INVOP)
+-	detail->code = ILL_INVOPR_FAULT;
+-      else if (detail->exc_code == EXC_I386_STKFLT)
+-	detail->code = ILL_STACK_FAULT;
+-      else
+-	detail->code = 0;
++      switch (detail->exc_code)
++        {
++	case EXC_I386_INVOP:
++	  detail->code = posix ? ILL_ILLOPC : ILL_INVOPR_FAULT;
++	  break;
++
++	case EXC_I386_STKFLT:
++	  detail->code = posix ? ILL_BADSTK : ILL_STACK_FAULT;
++	  break;
++
++	default:
++	  detail->code = 0;
++	  break;
++	}
+       break;
+ 
+     case EXC_ARITHMETIC:
++      *signo = SIGFPE;
+       switch (detail->exc_code)
+ 	{
+ 	case EXC_I386_DIV:	/* integer divide by zero */
+-	  *signo = SIGFPE;
+-	  detail->code = FPE_INTDIV_FAULT;
++	  detail->code = posix ? FPE_INTDIV : FPE_INTDIV_FAULT;
+ 	  break;
+ 
+ 	case EXC_I386_INTO:	/* integer overflow */
+-	  *signo = SIGFPE;
+-	  detail->code = FPE_INTOVF_TRAP;
++	  detail->code = posix ? FPE_INTOVF : FPE_INTOVF_TRAP;
+ 	  break;
+ 
+ 	  /* These aren't anywhere documented or used in Mach 3.0.  */
+ 	case EXC_I386_NOEXT:
+ 	case EXC_I386_EXTOVR:
+ 	default:
+-	  *signo = SIGFPE;
+ 	  detail->code = 0;
+ 	  break;
+ 
+@@ -83,51 +101,43 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+ 	     Give an error code corresponding to the first bit set.  */
+ 	  if (detail->exc_subcode & FPS_IE)
+ 	    {
+-	      *signo = SIGILL;
+-	      detail->code = ILL_FPEOPR_FAULT;
++	      /* NB: We used to send SIGILL here but we can't distinguish
++		 POSIX vs. legacy with respect to what signal we send.  */
++	      detail->code = posix ? FPE_FLTINV : 0 /*ILL_FPEOPR_FAULT*/;
+ 	    }
+ 	  else if (detail->exc_subcode & FPS_DE)
+ 	    {
+-	      *signo = SIGFPE;
+-	      detail->code = FPE_FLTDNR_FAULT;
++	      detail->code = posix ? FPE_FLTUND : FPE_FLTDNR_FAULT;
+ 	    }
+ 	  else if (detail->exc_subcode & FPS_ZE)
+ 	    {
+-	      *signo = SIGFPE;
+-	      detail->code = FPE_FLTDIV_FAULT;
++	      detail->code = posix ? FPE_FLTDIV : FPE_FLTDIV_FAULT;
+ 	    }
+ 	  else if (detail->exc_subcode & FPS_OE)
+ 	    {
+-	      *signo = SIGFPE;
+-	      detail->code = FPE_FLTOVF_FAULT;
++	      detail->code = posix ? FPE_FLTOVF : FPE_FLTOVF_FAULT;
+ 	    }
+ 	  else if (detail->exc_subcode & FPS_UE)
+ 	    {
+-	      *signo = SIGFPE;
+-	      detail->code = FPE_FLTUND_FAULT;
++	      detail->code = posix ? FPE_FLTUND : FPE_FLTUND_FAULT;
+ 	    }
+ 	  else if (detail->exc_subcode & FPS_PE)
+ 	    {
+-	      *signo = SIGFPE;
+-	      detail->code = FPE_FLTINX_FAULT;
++	      detail->code = posix ? FPE_FLTRES : FPE_FLTINX_FAULT;
+ 	    }
+ 	  else
+ 	    {
+-	      *signo = SIGFPE;
+ 	      detail->code = 0;
+ 	    }
+ 	  break;
+ 
+ 	  /* These two can only be arithmetic exceptions if we
+-	     are in V86 mode, which sounds like emulation to me.
+-	     (See Mach 3.0 i386/trap.c.)  */
++	     are in V86 mode.  (See Mach 3.0 i386/trap.c.)  */
+ 	case EXC_I386_EMERR:
+-	  *signo = SIGFPE;
+-	  detail->code = FPE_EMERR_FAULT;
++	  detail->code = posix ? 0 : FPE_EMERR_FAULT;
+ 	  break;
+ 	case EXC_I386_BOUND:
+-	  *signo = SIGFPE;
+-	  detail->code = FPE_EMBND_FAULT;
++	  detail->code = posix ? FPE_FLTSUB : FPE_EMBND_FAULT;
+ 	  break;
+ 	}
+       break;
+@@ -144,7 +154,7 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+       if (detail->exc_code == EXC_I386_BOUND)
+ 	{
+ 	  *signo = SIGFPE;
+-	  detail->code = FPE_SUBRNG_FAULT;
++	  detail->code = posix ? FPE_FLTSUB : FPE_SUBRNG_FAULT;
+ 	}
+       else
+ 	{
+@@ -155,12 +165,33 @@ _hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
+ 
+     case EXC_BREAKPOINT:
+       *signo = SIGTRAP;
+-      if (detail->exc_code == EXC_I386_SGL)
+-	detail->code = DBG_SINGLE_TRAP;
+-      else if (detail->exc_code == EXC_I386_BPT)
+-	detail->code = DBG_BRKPNT_FAULT;
+-      else
+-	detail->code = 0;
++      switch (detail->exc_code)
++        {
++	case EXC_I386_SGL:
++	  detail->code = posix ? TRAP_BRKPT : DBG_SINGLE_TRAP;
++	  break;
++
++	case EXC_I386_BPT:
++	  detail->code = posix ? TRAP_BRKPT : DBG_BRKPNT_FAULT;
++	  break;
++
++	default:
++	  detail->code = 0;
++	  break;
++	}
+       break;
+     }
+ }
++
++void
++_hurd_exception2signal (struct hurd_signal_detail *detail, int *signo)
++{
++  exception2signal (detail, signo, 1);
++}
++
++void
++_hurd_exception2signal_legacy (struct hurd_signal_detail *detail, int *signo)
++{
++  exception2signal (detail, signo, 0);
++}
++
+diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
+index ec52847..5abd33d 100644
+--- a/sysdeps/mach/hurd/i386/trampoline.c
++++ b/sysdeps/mach/hurd/i386/trampoline.c
+@@ -21,13 +21,66 @@
+ #include <hurd/signal.h>
+ #include <hurd/userlink.h>
+ #include <thread_state.h>
++#include <mach/exception.h>
+ #include <mach/machine/eflags.h>
+ #include <assert.h>
+ #include <errno.h>
+ #include "hurdfault.h"
+ #include <intr-msg.h>
++#include <sys/ucontext.h>
+ 
+ 
++/* Fill in a siginfo_t structure for SA_SIGINFO-enabled handlers.  */
++static void fill_siginfo (siginfo_t *si, int signo,
++			  const struct hurd_signal_detail *detail,
++			  const struct machine_thread_all_state *state)
++{
++  si->si_signo = signo;
++  si->si_errno = detail->error;
++  si->si_code = detail->code;
++
++  /* XXX We would need a protocol change for sig_post to include
++   * this information.  */
++  si->si_pid = -1;
++  si->si_uid = -1;
++
++  /* Address of the faulting instruction or memory access.  */
++  if (detail->exc == EXC_BAD_ACCESS)
++    si->si_addr = (void *) detail->exc_subcode;
++  else
++    si->si_addr = (void *) state->basic.eip;
++
++  /* XXX On SIGCHLD, this should be the exit status of the child
++   * process.  We would need a protocol change for the proc server
++   * to send this information along with the signal.  */
++  si->si_status = 0;
++
++  si->si_band = 0;              /* SIGPOLL is not supported yet.  */
++  si->si_value.sival_int = 0;   /* sigqueue() is not supported yet.  */
++}
++
++/* Fill in a ucontext_t structure SA_SIGINFO-enabled handlers.  */
++static void fill_ucontext (ucontext_t *uc, const struct sigcontext *sc)
++{
++  uc->uc_flags = 0;
++  uc->uc_link = NULL;
++  uc->uc_sigmask = sc->sc_mask;
++  uc->uc_stack.ss_sp = (__ptr_t) sc->sc_esp;
++  uc->uc_stack.ss_size = 0;
++  uc->uc_stack.ss_flags = 0;
++
++  /* Registers.  */
++  memcpy (&uc->uc_mcontext.gregs[REG_GS], &sc->sc_gs,
++	  (REG_TRAPNO - REG_GS) * sizeof (int));
++  uc->uc_mcontext.gregs[REG_TRAPNO] = 0;
++  uc->uc_mcontext.gregs[REG_ERR] = 0;
++  memcpy (&uc->uc_mcontext.gregs[REG_EIP], &sc->sc_eip,
++	  (NGREG - REG_EIP) * sizeof (int));
++
++  /* XXX FPU state.  */
++  memset (&uc->uc_mcontext.fpregs, 0, sizeof (fpregset_t));
++}
++
+ struct sigcontext *
+ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+ 			int signo, struct hurd_signal_detail *detail,
+@@ -40,18 +93,37 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+   extern const void _hurd_intr_rpc_msg_in_trap;
+   extern const void _hurd_intr_rpc_msg_cx_sp;
+   extern const void _hurd_intr_rpc_msg_sp_restored;
++  struct sigaction *action;
+   void *volatile sigsp;
+   struct sigcontext *scp;
+   struct
+     {
+       int signo;
+-      long int sigcode;
+-      struct sigcontext *scp;	/* Points to ctx, below.  */
++      union
++	{
++	  /* Extra arguments for traditional signal handlers */
++	  struct
++	    {
++	      long int sigcode;
++	      struct sigcontext *scp;       /* Points to ctx, below.  */
++	    } legacy;
++
++	  /* Extra arguments for SA_SIGINFO handlers */
++	  struct
++	    {
++	      siginfo_t *siginfop;          /* Points to siginfo, below.  */
++	      ucontext_t *uctxp;            /* Points to uctx, below.  */
++	    } posix;
++	};
+       void *sigreturn_addr;
+       void *sigreturn_returns_here;
+       struct sigcontext *return_scp; /* Same; arg to sigreturn.  */
++
++      /* NB: sigreturn assumes link is next to ctx.  */
+       struct sigcontext ctx;
+       struct hurd_userlink link;
++      ucontext_t ucontext;
++      siginfo_t siginfo;
+     } *stackframe;
+ 
+   if (ss->context)
+@@ -143,15 +215,9 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+ 	  = &stackframe->link.thread.next;
+       ss->active_resources = &stackframe->link;
+ 
+-      /* Set up the arguments for the signal handler.  */
+-      stackframe->signo = signo;
+-      stackframe->sigcode = detail->code;
+-      stackframe->scp = stackframe->return_scp = scp = &stackframe->ctx;
+-      stackframe->sigreturn_addr = &__sigreturn;
+-      stackframe->sigreturn_returns_here = firewall; /* Crash on return.  */
+-
+       /* Set up the sigcontext from the current state of the thread.  */
+ 
++      scp = &stackframe->ctx;
+       scp->sc_onstack = ss->sigaltstack.ss_flags & SS_ONSTACK ? 1 : 0;
+ 
+       /* struct sigcontext is laid out so that starting at sc_gs mimics a
+@@ -165,6 +231,35 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+ 			      &state->fpu, &scp->sc_i386_float_state,
+ 			      sizeof (state->fpu));
+ 
++      /* Set up the arguments for the signal handler.  */
++      stackframe->signo = signo;
++      if (action->sa_flags & SA_SIGINFO)
++	{
++	  stackframe->posix.siginfop = &stackframe->siginfo;
++	  stackframe->posix.uctxp = &stackframe->ucontext;
++	  fill_siginfo (&stackframe->siginfo, signo, detail, state);
++	  fill_ucontext (&stackframe->ucontext, scp);
++	}
++      else
++	{
++	  if (detail->exc)
++	    {
++	      int nsigno;
++	      _hurd_exception2signal_legacy (detail, &nsigno);
++	      assert (nsigno == signo);
++	    }
++	  else
++	    detail->code = 0;
++
++	  stackframe->legacy.sigcode = detail->code;
++	  stackframe->legacy.scp = &stackframe->ctx;
++	}
++
++      /* Set up the bottom of the stack.  */
++      stackframe->sigreturn_addr = &__sigreturn;
++      stackframe->sigreturn_returns_here = firewall; /* Crash on return.  */
++      stackframe->return_scp = &stackframe->ctx;
++
+       _hurdsig_end_catch_fault ();
+ 
+       if (! ok)
+diff --git a/sysdeps/mach/hurd/kill.c b/sysdeps/mach/hurd/kill.c
+index a9946e0..ac7ffc7 100644
+--- a/sysdeps/mach/hurd/kill.c
++++ b/sysdeps/mach/hurd/kill.c
+@@ -65,7 +65,7 @@ __kill (pid_t pid, int sig)
+ 	    {
+ 	      if (msgport != MACH_PORT_NULL)
+ 		/* Send a signal message to his message port.  */
+-		return __msg_sig_post (msgport, sig, 0, refport);
++		return __msg_sig_post (msgport, sig, SI_USER, refport);
+ 
+ 	      /* The process has no message port.  Perhaps try direct
+ 		 frobnication of the task.  */
+diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c
+index fec64a8..c82bfcd 100644
+--- a/sysdeps/mach/hurd/setitimer.c
++++ b/sysdeps/mach/hurd/setitimer.c
+@@ -105,7 +105,7 @@ timer_thread (void)
+ 	  __msg_sig_post_request (_hurd_msgport,
+ 				  _hurd_itimer_port,
+ 				  MACH_MSG_TYPE_MAKE_SEND_ONCE,
+-				  SIGALRM, 0, __mach_task_self ());
++				  SIGALRM, SI_TIMER, __mach_task_self ());
+ 	  break;
+ 
+ 	case MACH_RCV_INTERRUPTED:
diff --git a/debian/patches/hurd-i386/submitted-hurdsig-fixes-2.diff b/debian/patches/hurd-i386/submitted-hurdsig-fixes-2.diff
new file mode 100644
index 0000000..f9fea2f
--- /dev/null
+++ b/debian/patches/hurd-i386/submitted-hurdsig-fixes-2.diff
@@ -0,0 +1,44 @@
+diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
+index 67037e8..44e067c 100644
+--- a/hurd/hurdsig.c
++++ b/hurd/hurdsig.c
+@@ -859,9 +859,7 @@ post_signal (struct hurd_sigstate *ss,
+     }
+ 
+   /* Handle receipt of a blocked signal, or any signal while stopped.  */
+-  if (act != ignore &&		/* Signals ignored now are forgotten now.  */
+-      __sigismember (&blocked, signo) ||
+-      (signo != SIGKILL && _hurd_stopped))
++  if (__sigismember (&blocked, signo) || (signo != SIGKILL && _hurd_stopped))
+     {
+       mark_pending ();
+       act = ignore;
+diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
+index a4f3055..c74998d 100644
+--- a/sysdeps/mach/hurd/fork.c
++++ b/sysdeps/mach/hurd/fork.c
+@@ -648,8 +648,10 @@ __fork (void)
+       err = __USEPORT (PROC, __proc_getpids (port, &_hurd_pid, &_hurd_ppid,
+ 					     &_hurd_orphaned));
+ 
+-      /* Forking clears the trace flag.  */
++      /* Forking clears the trace flag and pending masks.  */
+       __sigemptyset (&_hurdsig_traced);
++      __sigemptyset (&_hurd_global_sigstate->pending);
++      __sigemptyset (&ss->pending);
+ 
+       /* Run things that want to run in the child task to set up.  */
+       RUN_HOOK (_hurd_fork_child_hook, ());
+diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
+index 373da8d..2442e6f 100644
+--- a/sysdeps/mach/hurd/spawni.c
++++ b/sysdeps/mach/hurd/spawni.c
+@@ -241,7 +241,7 @@ __spawni (pid_t *pid, const char *file,
+ 
+   _hurd_sigstate_lock (ss);
+   ints[INIT_SIGMASK] = ss->blocked;
+-  ints[INIT_SIGPENDING] = _hurd_sigstate_pending (ss); /* XXX really? */
++  ints[INIT_SIGPENDING] = 0;
+   ints[INIT_SIGIGN] = 0;
+   /* Unless we were asked to reset all handlers to SIG_DFL,
+      pass down the set of signals that were set to SIG_IGN.  */
diff --git a/debian/patches/hurd-i386/submitted-hurdsig-fixes.diff b/debian/patches/hurd-i386/submitted-hurdsig-fixes.diff
new file mode 100644
index 0000000..994bd6f
--- /dev/null
+++ b/debian/patches/hurd-i386/submitted-hurdsig-fixes.diff
@@ -0,0 +1,352 @@
+diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
+index 7a6b1d5..74a01a6 100644
+--- a/hurd/hurdsig.c
++++ b/hurd/hurdsig.c
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,2001,2002,2005,2008
++/* Copyright (C) 1991,92,93,94,95,96,97,98,99,2000,2001,2002,2005,2008,2011
+    	Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+@@ -443,6 +443,30 @@ abort_all_rpcs (int signo, struct machine_thread_all_state *state, int live)
+       }
+ }
+ 
++/* Wake up any sigsuspend call that is blocking SS->thread.  SS must be
++   locked.  */
++static void
++wake_sigsuspend (struct hurd_sigstate *ss)
++{
++  error_t err;
++  mach_msg_header_t msg;
++
++  if (ss->suspended == MACH_PORT_NULL)
++    return;
++
++  /* There is a sigsuspend waiting.  Tell it to wake up.  */
++  msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
++  msg.msgh_remote_port = ss->suspended;
++  msg.msgh_local_port = MACH_PORT_NULL;
++  /* These values do not matter.  */
++  msg.msgh_id = 8675309; /* Jenny, Jenny.  */
++  ss->suspended = MACH_PORT_NULL;
++  err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
++      MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
++      MACH_PORT_NULL);
++  assert_perror (err);
++}
++
+ struct hurd_signal_preemptor *_hurdsig_preemptors = 0;
+ sigset_t _hurdsig_preempted_set;
+ 
+@@ -453,35 +477,18 @@ weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
+ #define STOPSIGS (sigmask (SIGTTIN) | sigmask (SIGTTOU) | \
+ 		  sigmask (SIGSTOP) | sigmask (SIGTSTP))
+ 
+-/* Deliver a signal.  SS is not locked.  */
+-void
+-_hurd_internal_post_signal (struct hurd_sigstate *ss,
+-			    int signo, struct hurd_signal_detail *detail,
+-			    mach_port_t reply_port,
+-			    mach_msg_type_name_t reply_port_type,
+-			    int untraced)
++/* Actual delivery of a single signal.  Called with SS unlocked.  When
++   the signal is delivered, return 1 with SS locked.  If the signal is
++   being traced, return 0 with SS unlocked.   */
++static int
++post_signal (struct hurd_sigstate *ss,
++	     int signo, struct hurd_signal_detail *detail,
++	     int untraced, void (*reply) (void))
+ {
+-  error_t err;
+   struct machine_thread_all_state thread_state;
+   enum { stop, ignore, core, term, handle } act;
+-  sighandler_t handler;
+-  sigset_t pending;
+   int ss_suspended;
+ 
+-  /* Reply to this sig_post message.  */
+-  __typeof (__msg_sig_post_reply) *reply_rpc
+-    = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply);
+-  void reply (void)
+-    {
+-      error_t err;
+-      if (reply_port == MACH_PORT_NULL)
+-	return;
+-      err = (*reply_rpc) (reply_port, reply_port_type, 0);
+-      reply_port = MACH_PORT_NULL;
+-      if (err != MACH_SEND_INVALID_DEST) /* Ignore dead reply port.  */
+-	assert_perror (err);
+-    }
+-
+   /* Mark the signal as pending.  */
+   void mark_pending (void)
+     {
+@@ -545,19 +552,23 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
+ 	ss_suspended = 1;
+     }
+ 
++  error_t err;
++  sighandler_t handler;
++
+   if (signo == 0)
+     {
+       if (untraced)
+-	/* This is PTRACE_CONTINUE.  */
+-	resume ();
++	{
++	  /* This is PTRACE_CONTINUE.  */
++	  act = ignore;
++	  resume ();
++	}
+ 
+       /* This call is just to check for pending signals.  */
+       __spin_lock (&ss->lock);
+-      goto check_pending_signals;
++      return 1;
+     }
+ 
+- post_signal:
+-
+   thread_state.set = 0;		/* We know nothing.  */
+ 
+   __spin_lock (&ss->lock);
+@@ -620,7 +631,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
+ 	    suspend ();
+ 	  __spin_unlock (&ss->lock);
+ 	  reply ();
+-	  return;
++	  return 0;
+ 	}
+ 
+       handler = ss->actions[signo].sa_handler;
+@@ -863,7 +874,7 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
+ 					 as a unit.  */
+ 				      crit ? 0 : signo, 1,
+ 				      &thread_state, &state_changed,
+-				      &reply)
++				      reply)
+ 		 != MACH_PORT_NULL);
+ 
+ 	    if (crit)
+@@ -949,6 +960,9 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
+ 	    && signo != SIGILL && signo != SIGTRAP)
+ 	  ss->actions[signo].sa_handler = SIG_DFL;
+ 
++	/* Any sigsuspend call must return after the handler does.  */
++	wake_sigsuspend (ss);
++
+ 	/* Start the thread running the handler (or possibly waiting for an
+ 	   RPC reply before running the handler).  */
+ 	err = __thread_set_state (ss->thread, MACHINE_THREAD_STATE_FLAVOR,
+@@ -962,95 +976,129 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
+       }
+     }
+ 
+-  /* The signal has either been ignored or is now being handled.  We can
+-     consider it delivered and reply to the killer.  */
+-  reply ();
++  return 1;
++}
+ 
+-  /* We get here unless the signal was fatal.  We still hold SS->lock.
+-     Check for pending signals, and loop to post them.  */
+-  {
+-    /* Return nonzero if SS has any signals pending we should worry about.
+-       We don't worry about any pending signals if we are stopped, nor if
+-       SS is in a critical section.  We are guaranteed to get a sig_post
+-       message before any of them become deliverable: either the SIGCONT
+-       signal, or a sig_post with SIGNO==0 as an explicit poll when the
+-       thread finishes its critical section.  */
+-    inline int signals_pending (void)
+-      {
+-	if (_hurd_stopped || __spin_lock_locked (&ss->critical_section_lock))
+-	  return 0;
+-	return pending = ss->pending & ~ss->blocked;
+-      }
++/* Return the set of pending signals in SS which should be delivered. */
++static sigset_t
++pending_signals (struct hurd_sigstate *ss)
++{
++  /* We don't worry about any pending signals if we are stopped, nor if
++     SS is in a critical section.  We are guaranteed to get a sig_post
++     message before any of them become deliverable: either the SIGCONT
++     signal, or a sig_post with SIGNO==0 as an explicit poll when the
++     thread finishes its critical section.  */
++  if (_hurd_stopped || __spin_lock_locked (&ss->critical_section_lock))
++    return 0;
+ 
+-  check_pending_signals:
+-    untraced = 0;
++  return ss->pending & ~ss->blocked;
++}
+ 
+-    if (signals_pending ())
+-      {
+-	for (signo = 1; signo < NSIG; ++signo)
+-	  if (__sigismember (&pending, signo))
+-	    {
+-	    deliver_pending:
+-	      __sigdelset (&ss->pending, signo);
+-	      *detail = ss->pending_data[signo];
+-	      __spin_unlock (&ss->lock);
+-	      goto post_signal;
+-	    }
+-      }
++/* Post the specified pending signals in SS and return 1.  If one of
++   them is traced, abort immediately and return 0.  SS must be locked on
++   entry and will be unlocked in all cases.  */
++static int
++post_pending (struct hurd_sigstate *ss, sigset_t pending, void (*reply) (void))
++{
++  int signo;
++  struct hurd_signal_detail detail;
+ 
+-    /* No pending signals left undelivered for this thread.
+-       If we were sent signal 0, we need to check for pending
+-       signals for all threads.  */
+-    if (signo == 0)
+-      {
+-	__spin_unlock (&ss->lock);
+-	__mutex_lock (&_hurd_siglock);
+-	for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
+-	  {
+-	    __spin_lock (&ss->lock);
+-	    for (signo = 1; signo < NSIG; ++signo)
+-	      if (__sigismember (&ss->pending, signo)
+-		  && (!__sigismember (&ss->blocked, signo)
+-		      /* We "deliver" immediately pending blocked signals whose
+-			 action might be to ignore, so that if ignored they are
+-			 dropped right away.  */
+-		      || ss->actions[signo].sa_handler == SIG_IGN
+-		      || ss->actions[signo].sa_handler == SIG_DFL))
+-		{
+-		  mutex_unlock (&_hurd_siglock);
+-		  goto deliver_pending;
+-		}
+-	    __spin_unlock (&ss->lock);
+-	  }
+-	__mutex_unlock (&_hurd_siglock);
+-      }
+-    else
++  for (signo = 1; signo < NSIG; ++signo)
++    if (__sigismember (&pending, signo))
+       {
+-	/* No more signals pending; SS->lock is still locked.
+-	   Wake up any sigsuspend call that is blocking SS->thread.  */
+-	if (ss->suspended != MACH_PORT_NULL)
+-	  {
+-	    /* There is a sigsuspend waiting.  Tell it to wake up.  */
+-	    error_t err;
+-	    mach_msg_header_t msg;
+-	    msg.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_MAKE_SEND, 0);
+-	    msg.msgh_remote_port = ss->suspended;
+-	    msg.msgh_local_port = MACH_PORT_NULL;
+-	    /* These values do not matter.  */
+-	    msg.msgh_id = 8675309; /* Jenny, Jenny.  */
+-	    ss->suspended = MACH_PORT_NULL;
+-	    err = __mach_msg (&msg, MACH_SEND_MSG, sizeof msg, 0,
+-			      MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
+-			      MACH_PORT_NULL);
+-	    assert_perror (err);
+-	  }
++	__sigdelset (&ss->pending, signo);
++	detail = ss->pending_data[signo];
+ 	__spin_unlock (&ss->lock);
++
++	/* Will reacquire the lock, except if the signal is traced.  */
++	if (! post_signal (ss, signo, &detail, 0, reply))
++	  return 0;
+       }
+-  }
+ 
+-  /* All pending signals delivered to all threads.
+-     Now we can send the reply message even for signal 0.  */
+-  reply ();
++  /* No more signals pending; SS->lock is still locked.  */
++  __spin_unlock (&ss->lock);
++
++  return 1;
++}
++
++/* Post all the pending signals of all threads and return 1.  If a traced
++   signal is encountered, abort immediately and return 0.  */
++static int
++post_all_pending_signals (void (*reply) (void))
++{
++  struct hurd_sigstate *ss;
++  sigset_t pending;
++
++  for (;;)
++    {
++      __mutex_lock (&_hurd_siglock);
++      for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
++        {
++	  __spin_lock (&ss->lock);
++
++	  pending = pending_signals (ss);
++	  if (pending)
++	    /* post_pending() below will unlock SS. */
++	    break;
++
++	  __spin_unlock (&ss->lock);
++	}
++      __mutex_unlock (&_hurd_siglock);
++
++      if (! pending)
++	return 1;
++      if (! post_pending (ss, pending, reply))
++	return 0;
++    }
++}
++
++/* Deliver a signal.  SS is not locked.  */
++void
++_hurd_internal_post_signal (struct hurd_sigstate *ss,
++			    int signo, struct hurd_signal_detail *detail,
++			    mach_port_t reply_port,
++			    mach_msg_type_name_t reply_port_type,
++			    int untraced)
++{
++  /* Reply to this sig_post message.  */
++  __typeof (__msg_sig_post_reply) *reply_rpc
++    = (untraced ? __msg_sig_post_untraced_reply : __msg_sig_post_reply);
++  void reply (void)
++    {
++      error_t err;
++      if (reply_port == MACH_PORT_NULL)
++	return;
++      err = (*reply_rpc) (reply_port, reply_port_type, 0);
++      reply_port = MACH_PORT_NULL;
++      if (err != MACH_SEND_INVALID_DEST) /* Ignore dead reply port.  */
++	assert_perror (err);
++    }
++
++  if (! post_signal (ss, signo, detail, untraced, reply))
++    return;
++
++  /* The signal was neither fatal nor traced.  We still hold SS->lock.  */
++  if (signo != 0)
++    {
++      /* The signal has either been ignored or is now being handled.  We can
++	 consider it delivered and reply to the killer.  */
++      reply ();
++
++      /* Post any pending signals for this thread.  */
++      if (! post_pending (ss, pending_signals (ss), reply))
++	return;
++    }
++  else
++    {
++      /* We need to check for pending signals for all threads.  */
++      __spin_unlock (&ss->lock);
++      if (! post_all_pending_signals (reply))
++	return;
++
++      /* All pending signals delivered to all threads.
++	 Now we can send the reply message even for signal 0.  */
++      reply ();
++    }
+ }
+ 
+ /* Decide whether REFPORT enables the sender to send us a SIGNO signal.
diff --git a/debian/patches/hurd-i386/submitted-hurdsig-global-dispositions.diff b/debian/patches/hurd-i386/submitted-hurdsig-global-dispositions.diff
new file mode 100644
index 0000000..50c7b54
--- /dev/null
+++ b/debian/patches/hurd-i386/submitted-hurdsig-global-dispositions.diff
@@ -0,0 +1,1238 @@
+diff --git a/Versions.def b/Versions.def
+index 98c2800..d20b95c 100644
+--- a/Versions.def
++++ b/Versions.def
+@@ -39,6 +39,7 @@ libc {
+   GCC_3.0
+ %endif
+   GLIBC_PRIVATE
++  GLIBC_2.13_DEBIAN_11
+ }
+ libcrypt {
+   GLIBC_2.0
+diff --git a/hurd/Versions b/hurd/Versions
+index 83c8ab1..b697019 100644
+--- a/hurd/Versions
++++ b/hurd/Versions
+@@ -156,6 +156,14 @@ libc {
+     # functions used in macros & inline functions
+     __errno_location;
+   }
++  GLIBC_2.13_DEBIAN_11 {
++    # functions used by libpthread and <hurd/signal.h>
++    _hurd_sigstate_set_global_rcv;
++    _hurd_sigstate_lock;
++    _hurd_sigstate_pending;
++    _hurd_sigstate_unlock;
++    _hurd_sigstate_delete;
++  }
+ 
+ %if !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
+   HURD_CTHREADS_0.3 {
+diff --git a/hurd/ctty-input.c b/hurd/ctty-input.c
+index ef8395a..4da33c7 100644
+--- a/hurd/ctty-input.c
++++ b/hurd/ctty-input.c
+@@ -1,5 +1,5 @@
+ /* _hurd_ctty_input -- Do an input RPC and generate SIGTTIN if necessary.
+-   Copyright (C) 1995,97,99 Free Software Foundation, Inc.
++   Copyright (C) 1995,97,99,2011 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
+@@ -44,12 +44,15 @@ _hurd_ctty_input (io_t port, io_t ctty, error_t (*rpc) (io_t))
+ 	  else
+ 	    {
+ 	      struct hurd_sigstate *ss = _hurd_self_sigstate ();
+-	      __spin_lock (&ss->lock);
++	      struct sigaction *actions;
++
++	      _hurd_sigstate_lock (ss);
++	      actions = _hurd_sigstate_actions (ss);
+ 	      if (__sigismember (&ss->blocked, SIGTTIN) ||
+-		  ss->actions[SIGTTIN].sa_handler == SIG_IGN)
++		  actions[SIGTTIN].sa_handler == SIG_IGN)
+ 		/* We are blocking or ignoring SIGTTIN.  Just fail.  */
+ 		err = EIO;
+-	      __spin_unlock (&ss->lock);
++	      _hurd_sigstate_unlock (ss);
+ 
+ 	      if (err == EBACKGROUND)
+ 		{
+@@ -66,10 +69,11 @@ _hurd_ctty_input (io_t port, io_t ctty, error_t (*rpc) (io_t))
+ 		     SIGTTIN or resumed after being stopped.  Now this is
+ 		     still a "system call", so check to see if we should
+ 		  restart it.  */
+-		  __spin_lock (&ss->lock);
+-		  if (!(ss->actions[SIGTTIN].sa_flags & SA_RESTART))
++		  _hurd_sigstate_lock (ss);
++		  actions = _hurd_sigstate_actions (ss);
++		  if (!(actions[SIGTTIN].sa_flags & SA_RESTART))
+ 		    err = EINTR;
+-		  __spin_unlock (&ss->lock);
++		  _hurd_sigstate_unlock (ss);
+ 		}
+ 	    }
+ 	}
+diff --git a/hurd/ctty-output.c b/hurd/ctty-output.c
+index 92ab95a..6e4bd74 100644
+--- a/hurd/ctty-output.c
++++ b/hurd/ctty-output.c
+@@ -1,5 +1,5 @@
+ /* _hurd_ctty_output -- Do an output RPC and generate SIGTTOU if necessary.
+-   Copyright (C) 1995,97,99 Free Software Foundation, Inc.
++   Copyright (C) 1995,97,99,2011 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
+@@ -35,16 +35,19 @@ _hurd_ctty_output (io_t port, io_t ctty, error_t (*rpc) (io_t))
+ 
+       do
+ 	{
++	  struct sigaction *actions;
++
+ 	  /* Don't use the ctty io port if we are blocking or ignoring
+ 	     SIGTTOU.  We redo this check at the top of the loop in case
+ 	     the signal handler changed the state.  */
+-	  __spin_lock (&ss->lock);
++	  _hurd_sigstate_lock (ss);
++	  actions = _hurd_sigstate_actions (ss);
+ 	  if (__sigismember (&ss->blocked, SIGTTOU) ||
+-	      ss->actions[SIGTTOU].sa_handler == SIG_IGN)
++	      actions[SIGTTOU].sa_handler == SIG_IGN)
+ 	    err = EIO;
+ 	  else
+ 	    err = 0;
+-	  __spin_unlock (&ss->lock);
++	  _hurd_sigstate_unlock (ss);
+ 
+ 	  if (err)
+ 	    return (*rpc) (port);
+@@ -71,10 +74,11 @@ _hurd_ctty_output (io_t port, io_t ctty, error_t (*rpc) (io_t))
+ 		     SIGTTOU or resumed after being stopped.  Now this is
+ 		     still a "system call", so check to see if we should
+ 		  restart it.  */
+-		  __spin_lock (&ss->lock);
+-		  if (!(ss->actions[SIGTTOU].sa_flags & SA_RESTART))
++		  _hurd_sigstate_lock (ss);
++		  actions = _hurd_sigstate_actions (ss);
++		  if (!(actions[SIGTTOU].sa_flags & SA_RESTART))
+ 		    err = EINTR;
+-		  __spin_unlock (&ss->lock);
++		  _hurd_sigstate_unlock (ss);
+ 		}
+ 	    }
+ 	  /* If the last RPC generated a SIGTTOU, loop to try it again.  */
+diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
+index 21e30c5..1c4733a 100644
+--- a/hurd/hurd/signal.h
++++ b/hurd/hurd/signal.h
+@@ -1,5 +1,5 @@
+ /* Implementing POSIX.1 signals under the Hurd.
+-   Copyright (C) 1993,94,95,96,98,99,2002,2007,2008
++   Copyright (C) 1993,94,95,96,98,99,2002,2007,2008,2011
+ 	Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+@@ -71,7 +71,13 @@ struct hurd_sigstate
+ 
+     sigset_t blocked;		/* What signals are blocked.  */
+     sigset_t pending;		/* Pending signals, possibly blocked.  */
++
++    /* Signal handlers.  ACTIONS[0] is used to mark the threads with POSIX
++       semantics: if sa_handler is SIG_IGN instead of SIG_DFL, this thread
++       will receive global signals and use the process-wide action vector
++       instead of this one.  */
+     struct sigaction actions[NSIG];
++
+     struct sigaltstack sigaltstack;
+ 
+     /* Chain of thread-local signal preemptors; see <hurd/sigpreempt.h>.
+@@ -127,6 +133,26 @@ extern struct hurd_sigstate *_hurd_self_sigstate (void)
+ 	by different threads.  */
+      __attribute__ ((__const__));
+ 
++/* Process-wide signal state.  */
++
++extern struct hurd_sigstate *_hurd_global_sigstate;
++
++/* Mark the given thread as a process-wide signal receiver.  */
++
++extern void _hurd_sigstate_set_global_rcv (struct hurd_sigstate *ss);
++
++/* A thread can either use its own action vector and pending signal set
++   or use the global ones, depending on wether it has been marked as a
++   global receiver. The accessors below take that into account.  */
++
++extern void _hurd_sigstate_lock (struct hurd_sigstate *ss);
++extern struct sigaction *_hurd_sigstate_actions (struct hurd_sigstate *ss);
++extern sigset_t _hurd_sigstate_pending (const struct hurd_sigstate *ss);
++extern void _hurd_sigstate_unlock (struct hurd_sigstate *ss);
++
++/* Used by libpthread to remove stale sigstate structures.  */
++extern void _hurd_sigstate_delete (thread_t thread);
++
+ #ifndef _HURD_SIGNAL_H_EXTERN_INLINE
+ #define _HURD_SIGNAL_H_EXTERN_INLINE __extern_inline
+ #endif
+@@ -150,12 +176,6 @@ extern thread_t _hurd_msgport_thread;
+ 
+ extern mach_port_t _hurd_msgport;
+ 
+-
+-/* Thread to receive process-global signals.  */
+-
+-extern thread_t _hurd_sigthread;
+-
+-
+ /* Resource limit on core file size.  Enforced by hurdsig.c.  */
+ extern int _hurd_core_limit;
+ 
+@@ -203,10 +223,10 @@ _hurd_critical_section_unlock (void *our_lock)
+       /* It was us who acquired the critical section lock.  Unlock it.  */
+       struct hurd_sigstate *ss = our_lock;
+       sigset_t pending;
+-      __spin_lock (&ss->lock);
++      _hurd_sigstate_lock (ss);
+       __spin_unlock (&ss->critical_section_lock);
+-      pending = ss->pending & ~ss->blocked;
+-      __spin_unlock (&ss->lock);
++      pending = _hurd_sigstate_pending(ss) & ~ss->blocked;
++      _hurd_sigstate_unlock (ss);
+       if (! __sigisemptyset (&pending))
+ 	/* There are unblocked signals pending, which weren't
+ 	   delivered because we were in the critical section.
+diff --git a/hurd/hurdexec.c b/hurd/hurdexec.c
+index beae869..ee3162f 100644
+--- a/hurd/hurdexec.c
++++ b/hurd/hurdexec.c
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 1991,92,93,94,95,96,97,99,2001,02
++/* Copyright (C) 1991,92,93,94,95,96,97,99,2001,2002,2011
+    	Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+@@ -109,12 +109,13 @@ _hurd_exec (task_t task, file_t file,
+   assert (! __spin_lock_locked (&ss->critical_section_lock));
+   __spin_lock (&ss->critical_section_lock);
+ 
+-  __spin_lock (&ss->lock);
++  _hurd_sigstate_lock (ss);
++  struct sigaction *actions = _hurd_sigstate_actions (ss);
+   ints[INIT_SIGMASK] = ss->blocked;
+-  ints[INIT_SIGPENDING] = ss->pending;
++  ints[INIT_SIGPENDING] = _hurd_sigstate_pending (ss);
+   ints[INIT_SIGIGN] = 0;
+   for (i = 1; i < NSIG; ++i)
+-    if (ss->actions[i].sa_handler == SIG_IGN)
++    if (actions[i].sa_handler == SIG_IGN)
+       ints[INIT_SIGIGN] |= __sigmask (i);
+ 
+   /* We hold the sigstate lock until the exec has failed so that no signal
+@@ -125,7 +126,7 @@ _hurd_exec (task_t task, file_t file,
+      critical section flag avoids anything we call trying to acquire the
+      sigstate lock.  */
+ 
+-  __spin_unlock (&ss->lock);
++  _hurd_sigstate_unlock (ss);
+ 
+   /* Pack up the descriptor table to give the new program.  */
+   __mutex_lock (&_hurd_dtable_lock);
+diff --git a/hurd/hurdmsg.c b/hurd/hurdmsg.c
+index ffcce61..fdc7551 100644
+--- a/hurd/hurdmsg.c
++++ b/hurd/hurdmsg.c
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 1992, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
++/* Copyright (C) 1992, 1994, 1995, 1996, 1997, 2011
++       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
+@@ -122,17 +123,9 @@ get_int (int which, int *value)
+     case INIT_UMASK:
+       *value = _hurd_umask;
+       return 0;
+-    case INIT_SIGMASK:
+-      {
+-	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
+-	__spin_lock (&ss->lock);
+-	*value = ss->blocked;
+-	__spin_unlock (&ss->lock);
+-	return 0;
+-      }
+     case INIT_SIGPENDING:
+       {
+-	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
++	struct hurd_sigstate *ss = _hurd_global_sigstate;
+ 	__spin_lock (&ss->lock);
+ 	*value = ss->pending;
+ 	__spin_unlock (&ss->lock);
+@@ -140,7 +133,7 @@ get_int (int which, int *value)
+       }
+     case INIT_SIGIGN:
+       {
+-	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
++	struct hurd_sigstate *ss = _hurd_global_sigstate;
+ 	sigset_t ign;
+ 	int sig;
+ 	__spin_lock (&ss->lock);
+@@ -208,17 +201,9 @@ set_int (int which, int value)
+       return 0;
+ 
+       /* These are pretty odd things to do.  But you asked for it.  */
+-    case INIT_SIGMASK:
+-      {
+-	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
+-	__spin_lock (&ss->lock);
+-	ss->blocked = value;
+-	__spin_unlock (&ss->lock);
+-	return 0;
+-      }
+     case INIT_SIGPENDING:
+       {
+-	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
++	struct hurd_sigstate *ss = _hurd_global_sigstate;
+ 	__spin_lock (&ss->lock);
+ 	ss->pending = value;
+ 	__spin_unlock (&ss->lock);
+@@ -226,7 +211,7 @@ set_int (int which, int value)
+       }
+     case INIT_SIGIGN:
+       {
+-	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
++	struct hurd_sigstate *ss = _hurd_global_sigstate;
+ 	int sig;
+ 	const sigset_t ign = value;
+ 	__spin_lock (&ss->lock);
+diff --git a/hurd/hurdsig.c b/hurd/hurdsig.c
+index 74a01a6..67037e8 100644
+--- a/hurd/hurdsig.c
++++ b/hurd/hurdsig.c
+@@ -44,9 +44,6 @@ mach_port_t _hurd_msgport;
+ /* Thread listening on it.  */
+ thread_t _hurd_msgport_thread;
+ 
+-/* Thread which receives task-global signals.  */
+-thread_t _hurd_sigthread;
+-
+ /* These are set up by _hurdsig_init.  */
+ unsigned long int __hurd_sigthread_stack_base;
+ unsigned long int __hurd_sigthread_stack_end;
+@@ -55,6 +52,9 @@ unsigned long int *__hurd_sigthread_variables;
+ /* Linked-list of per-thread signal state.  */
+ struct hurd_sigstate *_hurd_sigstates;
+ 
++/* Sigstate for the task-global signals.  */
++struct hurd_sigstate *_hurd_global_sigstate;
++
+ /* Timeout for RPC's after interrupt_operation. */
+ mach_msg_timeout_t _hurd_interrupted_rpc_timeout = 3000;
+ 
+@@ -83,7 +83,7 @@ _hurd_thread_sigstate (thread_t thread)
+     {
+       ss = malloc (sizeof (*ss));
+       if (ss == NULL)
+-	__libc_fatal ("hurd: Can't allocate thread sigstate\n");
++	__libc_fatal ("hurd: Can't allocate sigstate\n");
+       ss->thread = thread;
+       __spin_lock_init (&ss->lock);
+ 
+@@ -96,16 +96,19 @@ _hurd_thread_sigstate (thread_t thread)
+       ss->intr_port = MACH_PORT_NULL;
+       ss->context = NULL;
+ 
+-      /* Initialize the sigaction vector from the default signal receiving
+-	 thread's state, and its from the system defaults.  */
+-      if (thread == _hurd_sigthread)
+-	default_sigaction (ss->actions);
++      if (thread == MACH_PORT_NULL)
++	{
++	  /* Process-wide sigstate, use the system defaults.  */
++	  default_sigaction (ss->actions);
++
++	  /* The global sigstate is not added to the _hurd_sigstates list.
++	     It is created with _hurd_thread_sigstate (MACH_PORT_NULL)
++	     but should be accessed through _hurd_global_sigstate.  */
++	}
+       else
+ 	{
+-	  struct hurd_sigstate *s;
+-	  for (s = _hurd_sigstates; s != NULL; s = s->next)
+-	    if (s->thread == _hurd_sigthread)
+-	      break;
++	  /* Use the global actions as a default for new threads.  */
++	  struct hurd_sigstate *s = _hurd_global_sigstate;
+ 	  if (s)
+ 	    {
+ 	      __spin_lock (&s->lock);
+@@ -114,14 +117,108 @@ _hurd_thread_sigstate (thread_t thread)
+ 	    }
+ 	  else
+ 	    default_sigaction (ss->actions);
+-	}
+ 
+-      ss->next = _hurd_sigstates;
+-      _hurd_sigstates = ss;
++	  ss->next = _hurd_sigstates;
++	  _hurd_sigstates = ss;
++	}
+     }
+   __mutex_unlock (&_hurd_siglock);
+   return ss;
+ }
++
++/* Destroy a sigstate structure.  Called by libpthread just before the
++ * corresponding thread is terminated (the kernel thread port must remain valid
++ * until this function is called.) */
++void
++_hurd_sigstate_delete (thread_t thread)
++{
++  struct hurd_sigstate **ssp, *ss;
++
++  __mutex_lock (&_hurd_siglock);
++  for (ssp = &_hurd_sigstates; *ssp; ssp = &(*ssp)->next)
++    if ((*ssp)->thread == thread)
++      break;
++
++  ss = *ssp;
++  if (ss)
++    *ssp = ss->next;
++
++  __mutex_unlock (&_hurd_siglock);
++  if (ss)
++    free (ss);
++}
++
++/* Make SS a global receiver, with pthread signal semantics.  */
++void
++_hurd_sigstate_set_global_rcv (struct hurd_sigstate *ss)
++{
++  assert (ss->thread != MACH_PORT_NULL);
++  ss->actions[0].sa_handler = SIG_IGN;
++}
++
++/* Check whether SS is a global receiver.  */
++static int
++sigstate_is_global_rcv (const struct hurd_sigstate *ss)
++{
++  return ss->actions[0].sa_handler == SIG_IGN;
++}
++
++/* Lock/unlock a hurd_sigstate structure.  If the accessors below require
++   it, the global sigstate will be locked as well.  */
++void
++_hurd_sigstate_lock (struct hurd_sigstate *ss)
++{
++  if (sigstate_is_global_rcv (ss))
++    __spin_lock (&_hurd_global_sigstate->lock);
++  __spin_lock (&ss->lock);
++}
++void
++_hurd_sigstate_unlock (struct hurd_sigstate *ss)
++{
++  __spin_unlock (&ss->lock);
++  if (sigstate_is_global_rcv (ss))
++    __spin_unlock (&_hurd_global_sigstate->lock);
++}
++
++/* Retreive a thread's full set of pending signals, including the global
++   ones if appropriate.  SS must be locked.  */
++sigset_t
++_hurd_sigstate_pending (const struct hurd_sigstate *ss)
++{
++  sigset_t pending = ss->pending;
++  if (sigstate_is_global_rcv (ss))
++    __sigorset (&pending, &pending, &_hurd_global_sigstate->pending);
++  return pending;
++}
++
++/* Clear a pending signal and return the associated detailed
++   signal information. SS must be locked, and must have signal SIGNO
++   pending, either directly or through the global sigstate.  */
++static struct hurd_signal_detail
++sigstate_clear_pending (struct hurd_sigstate *ss, int signo)
++{
++  if (sigstate_is_global_rcv (ss)
++      && __sigismember (&_hurd_global_sigstate->pending, signo))
++    {
++      __sigdelset (&_hurd_global_sigstate->pending, signo);
++      return _hurd_global_sigstate->pending_data[signo];
++    }
++
++  assert (__sigismember (&ss->pending, signo));
++  __sigdelset (&ss->pending, signo);
++  return ss->pending_data[signo];
++}
++
++/* Retreive a thread's action vector.  SS must be locked.  */
++struct sigaction *
++_hurd_sigstate_actions (struct hurd_sigstate *ss)
++{
++  if (sigstate_is_global_rcv (ss))
++    return _hurd_global_sigstate->actions;
++  else
++    return ss->actions;
++}
++
+ 
+ /* Signal delivery itself is on this page.  */
+ 
+@@ -216,6 +313,8 @@ static void
+ abort_thread (struct hurd_sigstate *ss, struct machine_thread_all_state *state,
+ 	      void (*reply) (void))
+ {
++  assert (ss->thread != MACH_PORT_NULL);
++
+   if (!(state->set & THREAD_ABORTED))
+     {
+       error_t err = __thread_abort (ss->thread);
+@@ -355,7 +454,7 @@ _hurdsig_abort_rpcs (struct hurd_sigstate *ss, int signo, int sigthread,
+ 	   call above will retry their RPCs unless we clear SS->intr_port.
+ 	   So we clear it for the thread taking a signal when SA_RESTART is
+ 	   clear, so that its call returns EINTR.  */
+-	if (! signo || !(ss->actions[signo].sa_flags & SA_RESTART))
++	if (! signo || !(_hurd_sigstate_actions (ss) [signo].sa_flags & SA_RESTART))
+ 	  ss->intr_port = MACH_PORT_NULL;
+       }
+ 
+@@ -478,9 +577,11 @@ weak_alias (_hurdsig_preemptors, _hurdsig_preempters)
+ 		  sigmask (SIGSTOP) | sigmask (SIGTSTP))
+ 
+ /* Actual delivery of a single signal.  Called with SS unlocked.  When
+-   the signal is delivered, return 1 with SS locked.  If the signal is
+-   being traced, return 0 with SS unlocked.   */
+-static int
++   the signal is delivered, return SS, locked (or, if SS was originally
++   _hurd_global_sigstate, the sigstate of the actual thread the signal
++   was delivered to).  If the signal is being traced, return NULL with
++   SS unlocked.   */
++static struct hurd_sigstate *
+ post_signal (struct hurd_sigstate *ss,
+ 	     int signo, struct hurd_signal_detail *detail,
+ 	     int untraced, void (*reply) (void))
+@@ -533,8 +634,12 @@ post_signal (struct hurd_sigstate *ss,
+       assert_perror (err);
+       for (i = 0; i < nthreads; ++i)
+ 	{
+-	  if (threads[i] != _hurd_msgport_thread &&
+-	      (act != handle || threads[i] != ss->thread))
++	  if (act == handle && threads[i] == ss->thread)
++	    {
++	      /* The thread that will run the handler is kept suspended.  */
++	      ss_suspended = 1;
++	    }
++	  else if (threads[i] != _hurd_msgport_thread)
+ 	    {
+ 	      err = __thread_resume (threads[i]);
+ 	      assert_perror (err);
+@@ -547,9 +652,6 @@ post_signal (struct hurd_sigstate *ss,
+ 		       (vm_address_t) threads,
+ 		       nthreads * sizeof *threads);
+       _hurd_stopped = 0;
+-      if (act == handle)
+-	/* The thread that will run the handler is already suspended.  */
+-	ss_suspended = 1;
+     }
+ 
+   error_t err;
+@@ -565,13 +667,43 @@ post_signal (struct hurd_sigstate *ss,
+ 	}
+ 
+       /* This call is just to check for pending signals.  */
+-      __spin_lock (&ss->lock);
+-      return 1;
++      _hurd_sigstate_lock (ss);
++      return ss;
+     }
+ 
+   thread_state.set = 0;		/* We know nothing.  */
+ 
+-  __spin_lock (&ss->lock);
++  _hurd_sigstate_lock (ss);
++
++  /* If this is a global signal, try to find a thread ready to accept
++     it right away.  This is especially important for untraced signals,
++     since going through the global pending mask would de-untrace them.  */
++  if (ss->thread == MACH_PORT_NULL)
++  {
++    struct hurd_sigstate *rss;
++
++    __mutex_lock (&_hurd_siglock);
++    for (rss = _hurd_sigstates; rss != NULL; rss = rss->next)
++      {
++	if (! sigstate_is_global_rcv (rss))
++	  continue;
++
++	/* The global sigstate is already locked.  */
++	__spin_lock (&rss->lock);
++	if (! __sigismember (&rss->blocked, signo))
++	  {
++	    ss = rss;
++	    break;
++	  }
++	__spin_unlock (&rss->lock);
++      }
++    __mutex_unlock (&_hurd_siglock);
++  }
++
++  /* We want the preemptors to be able to update the blocking mask
++     without affecting the delivery of this signal, so we save the
++     current value to test against later.  */
++  sigset_t blocked = ss->blocked;
+ 
+   /* Check for a preempted signal.  Preempted signals can arrive during
+      critical sections.  */
+@@ -629,12 +761,12 @@ post_signal (struct hurd_sigstate *ss,
+ 	    mark_pending ();
+ 	  else
+ 	    suspend ();
+-	  __spin_unlock (&ss->lock);
++	  _hurd_sigstate_unlock (ss);
+ 	  reply ();
+-	  return 0;
++	  return NULL;
+ 	}
+ 
+-      handler = ss->actions[signo].sa_handler;
++      handler = _hurd_sigstate_actions (ss) [signo].sa_handler;
+ 
+       if (handler == SIG_DFL)
+ 	/* Figure out the default action for this signal.  */
+@@ -728,7 +860,7 @@ post_signal (struct hurd_sigstate *ss,
+ 
+   /* Handle receipt of a blocked signal, or any signal while stopped.  */
+   if (act != ignore &&		/* Signals ignored now are forgotten now.  */
+-      __sigismember (&ss->blocked, signo) ||
++      __sigismember (&blocked, signo) ||
+       (signo != SIGKILL && _hurd_stopped))
+     {
+       mark_pending ();
+@@ -764,6 +896,7 @@ post_signal (struct hurd_sigstate *ss,
+ 	 now's the time to set it going. */
+       if (ss_suspended)
+ 	{
++	  assert (ss->thread != MACH_PORT_NULL);
+ 	  err = __thread_resume (ss->thread);
+ 	  assert_perror (err);
+ 	  ss_suspended = 0;
+@@ -808,6 +941,8 @@ post_signal (struct hurd_sigstate *ss,
+ 	struct sigcontext *scp, ocontext;
+ 	int wait_for_reply, state_changed;
+ 
++	assert (ss->thread != MACH_PORT_NULL);
++
+ 	/* Stop the thread and abort its pending RPC operations.  */
+ 	if (! ss_suspended)
+ 	  {
+@@ -942,23 +1077,25 @@ post_signal (struct hurd_sigstate *ss,
+ 	    }
+ 	}
+ 
++	struct sigaction *action = & _hurd_sigstate_actions (ss) [signo];
++
+ 	/* Backdoor extra argument to signal handler.  */
+ 	scp->sc_error = detail->error;
+ 
+ 	/* Block requested signals while running the handler.  */
+ 	scp->sc_mask = ss->blocked;
+-	__sigorset (&ss->blocked, &ss->blocked, &ss->actions[signo].sa_mask);
++	__sigorset (&ss->blocked, &ss->blocked, &action->sa_mask);
+ 
+ 	/* Also block SIGNO unless we're asked not to.  */
+-	if (! (ss->actions[signo].sa_flags & (SA_RESETHAND | SA_NODEFER)))
++	if (! (action->sa_flags & (SA_RESETHAND | SA_NODEFER)))
+ 	  __sigaddset (&ss->blocked, signo);
+ 
+ 	/* Reset to SIG_DFL if requested.  SIGILL and SIGTRAP cannot
+            be automatically reset when delivered; the system silently
+            enforces this restriction.  */
+-	if (ss->actions[signo].sa_flags & SA_RESETHAND
++	if (action->sa_flags & SA_RESETHAND
+ 	    && signo != SIGILL && signo != SIGTRAP)
+-	  ss->actions[signo].sa_handler = SIG_DFL;
++	  action->sa_handler = SIG_DFL;
+ 
+ 	/* Any sigsuspend call must return after the handler does.  */
+ 	wake_sigsuspend (ss);
+@@ -976,7 +1113,7 @@ post_signal (struct hurd_sigstate *ss,
+       }
+     }
+ 
+-  return 1;
++  return ss;
+ }
+ 
+ /* Return the set of pending signals in SS which should be delivered. */
+@@ -991,7 +1128,7 @@ pending_signals (struct hurd_sigstate *ss)
+   if (_hurd_stopped || __spin_lock_locked (&ss->critical_section_lock))
+     return 0;
+ 
+-  return ss->pending & ~ss->blocked;
++  return _hurd_sigstate_pending (ss) & ~ss->blocked;
+ }
+ 
+ /* Post the specified pending signals in SS and return 1.  If one of
+@@ -1003,12 +1140,15 @@ post_pending (struct hurd_sigstate *ss, sigset_t pending, void (*reply) (void))
+   int signo;
+   struct hurd_signal_detail detail;
+ 
++  /* Make sure SS corresponds to an actual thread, since we assume it won't
++     change in post_signal. */
++  assert (ss->thread != MACH_PORT_NULL);
++
+   for (signo = 1; signo < NSIG; ++signo)
+     if (__sigismember (&pending, signo))
+       {
+-	__sigdelset (&ss->pending, signo);
+-	detail = ss->pending_data[signo];
+-	__spin_unlock (&ss->lock);
++	detail = sigstate_clear_pending (ss, signo);
++	_hurd_sigstate_unlock (ss);
+ 
+ 	/* Will reacquire the lock, except if the signal is traced.  */
+ 	if (! post_signal (ss, signo, &detail, 0, reply))
+@@ -1016,7 +1156,7 @@ post_pending (struct hurd_sigstate *ss, sigset_t pending, void (*reply) (void))
+       }
+ 
+   /* No more signals pending; SS->lock is still locked.  */
+-  __spin_unlock (&ss->lock);
++  _hurd_sigstate_unlock (ss);
+ 
+   return 1;
+ }
+@@ -1034,14 +1174,14 @@ post_all_pending_signals (void (*reply) (void))
+       __mutex_lock (&_hurd_siglock);
+       for (ss = _hurd_sigstates; ss != NULL; ss = ss->next)
+         {
+-	  __spin_lock (&ss->lock);
++	  _hurd_sigstate_lock (ss);
+ 
+ 	  pending = pending_signals (ss);
+ 	  if (pending)
+ 	    /* post_pending() below will unlock SS. */
+ 	    break;
+ 
+-	  __spin_unlock (&ss->lock);
++	  _hurd_sigstate_unlock (ss);
+ 	}
+       __mutex_unlock (&_hurd_siglock);
+ 
+@@ -1074,11 +1214,12 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
+ 	assert_perror (err);
+     }
+ 
+-  if (! post_signal (ss, signo, detail, untraced, reply))
++  ss = post_signal (ss, signo, detail, untraced, reply);
++  if (! ss)
+     return;
+ 
+   /* The signal was neither fatal nor traced.  We still hold SS->lock.  */
+-  if (signo != 0)
++  if (signo != 0 && ss->thread != MACH_PORT_NULL)
+     {
+       /* The signal has either been ignored or is now being handled.  We can
+ 	 consider it delivered and reply to the killer.  */
+@@ -1090,8 +1231,9 @@ _hurd_internal_post_signal (struct hurd_sigstate *ss,
+     }
+   else
+     {
+-      /* We need to check for pending signals for all threads.  */
+-      __spin_unlock (&ss->lock);
++      /* If this was a process-wide signal or a poll request, we need
++	 to check for pending signals for all threads.  */
++      _hurd_sigstate_unlock (ss);
+       if (! post_all_pending_signals (reply))
+ 	return;
+ 
+@@ -1217,9 +1359,10 @@ _S_msg_sig_post (mach_port_t me,
+   d.code = sigcode;
+   d.exc = 0;
+ 
+-  /* Post the signal to the designated signal-receiving thread.  This will
+-     reply when the signal can be considered delivered.  */
+-  _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
++  /* Post the signal to a global receiver thread (or mark it pending in
++     the global sigstate).  This will reply when the signal can be
++     considered delivered.  */
++  _hurd_internal_post_signal (_hurd_global_sigstate,
+ 			      signo, &d, reply_port, reply_port_type,
+ 			      0); /* Stop if traced.  */
+ 
+@@ -1247,7 +1390,7 @@ _S_msg_sig_post_untraced (mach_port_t me,
+ 
+   /* Post the signal to the designated signal-receiving thread.  This will
+      reply when the signal can be considered delivered.  */
+-  _hurd_internal_post_signal (_hurd_thread_sigstate (_hurd_sigthread),
++  _hurd_internal_post_signal (_hurd_global_sigstate,
+ 			      signo, &d, reply_port, reply_port_type,
+ 			      1); /* Untraced flag. */
+ 
+@@ -1258,8 +1401,8 @@ extern void __mig_init (void *);
+ 
+ #include <mach/task_special_ports.h>
+ 
+-/* Initialize the message port and _hurd_sigthread and start the signal
+-   thread.  */
++/* Initialize the message port, _hurd_global_sigstate, and start the
++   signal thread.  */
+ 
+ void
+ _hurdsig_init (const int *intarray, size_t intarraysize)
+@@ -1282,27 +1425,34 @@ _hurdsig_init (const int *intarray, size_t intarraysize)
+ 				  MACH_MSG_TYPE_MAKE_SEND);
+   assert_perror (err);
+ 
++  /* Initialize the global signal state.  */
++  _hurd_global_sigstate = _hurd_thread_sigstate (MACH_PORT_NULL);
++
++  /* We block all signals, and let actual threads pull them from the
++     pending mask.  */
++  __sigfillset(& _hurd_global_sigstate->blocked);
++
+   /* Initialize the main thread's signal state.  */
+   ss = _hurd_self_sigstate ();
+ 
+-  /* Copy inherited values from our parent (or pre-exec process state)
+-     into the signal settings of the main thread.  */
++  /* Mark it as a process-wide signal receiver.  Threads in this set use
++     the common action vector in _hurd_global_sigstate.  */
++  _hurd_sigstate_set_global_rcv (ss);
++
++  /* Copy inherited signal settings from our parent (or pre-exec process
++     state) */
+   if (intarraysize > INIT_SIGMASK)
+     ss->blocked = intarray[INIT_SIGMASK];
+   if (intarraysize > INIT_SIGPENDING)
+-    ss->pending = intarray[INIT_SIGPENDING];
++    _hurd_global_sigstate->pending = intarray[INIT_SIGPENDING];
+   if (intarraysize > INIT_SIGIGN && intarray[INIT_SIGIGN] != 0)
+     {
+       int signo;
+       for (signo = 1; signo < NSIG; ++signo)
+ 	if (intarray[INIT_SIGIGN] & __sigmask(signo))
+-	  ss->actions[signo].sa_handler = SIG_IGN;
++	  _hurd_global_sigstate->actions[signo].sa_handler = SIG_IGN;
+     }
+ 
+-  /* Set the default thread to receive task-global signals
+-     to this one, the main (first) user thread.  */
+-  _hurd_sigthread = ss->thread;
+-
+   /* Start the signal thread listening on the message port.  */
+ 
+   if (__hurd_threadvar_stack_mask == 0)
+diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
+index 3288f18..a4f3055 100644
+--- a/sysdeps/mach/hurd/fork.c
++++ b/sysdeps/mach/hurd/fork.c
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 1994,1995,1996,1997,1999,2001,2002,2004,2005,2006
++/* Copyright (C) 1994,1995,1996,1997,1999,2001,2002,2004,2005,2006,2011
+ 	Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+@@ -459,6 +459,7 @@ __fork (void)
+ 	 function, accounted for by mach_port_names (and which will thus be
+ 	 accounted for in the child below).  This extra right gets consumed
+ 	 in the child by the store into _hurd_sigthread in the child fork.  */
++      /* XXX consumed? (_hurd_sigthread is no more) */
+       if (thread_refs > 1 &&
+ 	  (err = __mach_port_mod_refs (newtask, ss->thread,
+ 				       MACH_PORT_RIGHT_SEND,
+@@ -616,10 +617,6 @@ __fork (void)
+       for (i = 0; i < _hurd_nports; ++i)
+ 	__spin_unlock (&_hurd_ports[i].lock);
+ 
+-      /* We are one of the (exactly) two threads in this new task, we
+-	 will take the task-global signals.  */
+-      _hurd_sigthread = ss->thread;
+-
+       /* Claim our sigstate structure and unchain the rest: the
+ 	 threads existed in the parent task but don't exist in this
+ 	 task (the child process).  Delay freeing them until later
+@@ -640,6 +637,10 @@ __fork (void)
+       _hurd_sigstates = ss;
+       __mutex_unlock (&_hurd_siglock);
+ 
++      /* We are one of the (exactly) two threads in this new task, we
++	 will take the task-global signals.  */
++      _hurd_sigstate_set_global_rcv (ss);
++
+       /* Fetch our new process IDs from the proc server.  No need to
+ 	 refetch our pgrp; it is always inherited from the parent (so
+ 	 _hurd_pgrp is already correct), and the proc server will send us a
+diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
+index 60b0d00..8cb92ef 100644
+--- a/sysdeps/mach/hurd/i386/sigreturn.c
++++ b/sysdeps/mach/hurd/i386/sigreturn.c
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 1991,92,94,95,96,97,98,2001 Free Software Foundation, Inc.
++/* Copyright (C) 1991,92,94,95,96,97,98,2001,2011
++       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
+@@ -39,7 +40,7 @@ __sigreturn (struct sigcontext *scp)
+     }
+ 
+   ss = _hurd_self_sigstate ();
+-  __spin_lock (&ss->lock);
++  _hurd_sigstate_lock (ss);
+ 
+   /* Remove the link on the `active resources' chain added by
+      _hurd_setup_sighandler.  Its purpose was to make sure
+@@ -51,19 +52,19 @@ __sigreturn (struct sigcontext *scp)
+   ss->intr_port = scp->sc_intr_port;
+ 
+   /* Check for pending signals that were blocked by the old set.  */
+-  if (ss->pending & ~ss->blocked)
++  if (_hurd_sigstate_pending (ss) & ~ss->blocked)
+     {
+       /* There are pending signals that just became unblocked.  Wake up the
+ 	 signal thread to deliver them.  But first, squirrel away SCP where
+ 	 the signal thread will notice it if it runs another handler, and
+ 	 arrange to have us called over again in the new reality.  */
+       ss->context = scp;
+-      __spin_unlock (&ss->lock);
++      _hurd_sigstate_unlock (ss);
+       __msg_sig_post (_hurd_msgport, 0, 0, __mach_task_self ());
+       /* If a pending signal was handled, sig_post never returned.
+ 	 If it did return, the pending signal didn't run a handler;
+ 	 proceed as usual.  */
+-      __spin_lock (&ss->lock);
++      _hurd_sigstate_lock (ss);
+       ss->context = NULL;
+     }
+ 
+@@ -74,7 +75,7 @@ __sigreturn (struct sigcontext *scp)
+       abort ();
+     }
+   else
+-    __spin_unlock (&ss->lock);
++    _hurd_sigstate_unlock (ss);
+ 
+   /* Destroy the MiG reply port used by the signal handler, and restore the
+      reply port in use by the thread when interrupted.  */
+diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
+index 99d9308..ec52847 100644
+--- a/sysdeps/mach/hurd/i386/trampoline.c
++++ b/sysdeps/mach/hurd/i386/trampoline.c
+@@ -1,5 +1,5 @@
+ /* Set thread_state for sighandler, and sigcontext to recover.  i386 version.
+-   Copyright (C) 1994,1995,1996,1997,1998,1999,2005,2008
++   Copyright (C) 1994,1995,1996,1997,1998,1999,2005,2008,2011
+ 	Free Software Foundation, Inc.
+    This file is part of the GNU C Library.
+ 
+@@ -77,7 +77,11 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+      interrupted RPC frame.  */
+   state->basic.esp = state->basic.uesp;
+ 
+-  if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
++  /* XXX what if handler != action->handler (for instance, if a signal
++   * preemptor took over) ? */
++  action = & _hurd_sigstate_actions (ss) [signo];
++
++  if ((action->sa_flags & SA_ONSTACK) &&
+       !(ss->sigaltstack.ss_flags & (SS_DISABLE|SS_ONSTACK)))
+     {
+       sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
+diff --git a/sysdeps/mach/hurd/sigaction.c b/sysdeps/mach/hurd/sigaction.c
+index fe452e8..bedf14c 100644
+--- a/sysdeps/mach/hurd/sigaction.c
++++ b/sysdeps/mach/hurd/sigaction.c
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2002, 2007
++/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2002, 2007, 2011
+      Free Software Foundation, Inc.
+ 
+    This file is part of the GNU C Library.
+@@ -51,15 +51,15 @@ __sigaction (sig, act, oact)
+   ss = _hurd_self_sigstate ();
+ 
+   __spin_lock (&ss->critical_section_lock);
+-  __spin_lock (&ss->lock);
+-  old = ss->actions[sig];
++  _hurd_sigstate_lock (ss);
++  old = _hurd_sigstate_actions (ss) [sig];
+   if (act != NULL)
+-    ss->actions[sig] = a;
++    _hurd_sigstate_actions (ss) [sig] = a;
+ 
+   if (act != NULL && sig == SIGCHLD &&
+       (a.sa_flags & SA_NOCLDSTOP) != (old.sa_flags & SA_NOCLDSTOP))
+     {
+-      __spin_unlock (&ss->lock);
++      _hurd_sigstate_unlock (ss);
+ 
+       /* Inform the proc server whether or not it should send us SIGCHLD for
+ 	 stopped children.  We do this in a critical section so that no
+@@ -67,8 +67,8 @@ __sigaction (sig, act, oact)
+       __USEPORT (PROC,
+ 		 __proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP)));
+ 
+-      __spin_lock (&ss->lock);
+-      pending = ss->pending & ~ss->blocked;
++      _hurd_sigstate_lock (ss);
++      pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
+     }
+   else if (act != NULL && (a.sa_handler == SIG_IGN || a.sa_handler == SIG_DFL))
+     /* We are changing to an action that might be to ignore SIG signals.
+@@ -77,11 +77,11 @@ __sigaction (sig, act, oact)
+        back and then SIG is unblocked, the signal pending now should not
+        arrive.  So wake up the signal thread to check the new state and do
+        the right thing.  */
+-    pending = ss->pending & __sigmask (sig);
++    pending = _hurd_sigstate_pending (ss) & __sigmask (sig);
+   else
+     pending = 0;
+ 
+-  __spin_unlock (&ss->lock);
++  _hurd_sigstate_unlock (ss);
+   __spin_unlock (&ss->critical_section_lock);
+ 
+   if (pending)
+diff --git a/sysdeps/mach/hurd/sigpending.c b/sysdeps/mach/hurd/sigpending.c
+index 84ac927..f582d45 100644
+--- a/sysdeps/mach/hurd/sigpending.c
++++ b/sysdeps/mach/hurd/sigpending.c
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 1991, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
++/* Copyright (C) 1991, 1993, 1994, 1995, 1997, 2011
++       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
+@@ -38,9 +39,9 @@ sigpending (set)
+     }
+ 
+   ss = _hurd_self_sigstate ();
+-  __spin_lock (&ss->lock);
+-  pending = ss->pending;
+-  __spin_unlock (&ss->lock);
++  _hurd_sigstate_lock (ss);
++  pending = _hurd_sigstate_pending (ss);
++  _hurd_sigstate_unlock (ss);
+ 
+   *set = pending;
+   return 0;
+diff --git a/sysdeps/mach/hurd/sigprocmask.c b/sysdeps/mach/hurd/sigprocmask.c
+index cbb5ecc..b12dc19 100644
+--- a/sysdeps/mach/hurd/sigprocmask.c
++++ b/sysdeps/mach/hurd/sigprocmask.c
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 1991,92,93,94,95,96,97,2002 Free Software Foundation, Inc.
++/* Copyright (C) 1991,92,93,94,95,96,97,2002,2011
++       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
+@@ -40,7 +41,7 @@ __sigprocmask (how, set, oset)
+ 
+   ss = _hurd_self_sigstate ();
+ 
+-  __spin_lock (&ss->lock);
++  _hurd_sigstate_lock (ss);
+ 
+   old = ss->blocked;
+ 
+@@ -61,7 +62,7 @@ __sigprocmask (how, set, oset)
+ 	  break;
+ 
+ 	default:
+-	  __spin_unlock (&ss->lock);
++	  _hurd_sigstate_unlock (ss);
+ 	  errno = EINVAL;
+ 	  return -1;
+ 	}
+@@ -69,9 +70,9 @@ __sigprocmask (how, set, oset)
+       ss->blocked &= ~_SIG_CANT_MASK;
+     }
+ 
+-  pending = ss->pending & ~ss->blocked;
++  pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
+ 
+-  __spin_unlock (&ss->lock);
++  _hurd_sigstate_unlock (ss);
+ 
+   if (oset != NULL)
+     *oset = old;
+diff --git a/sysdeps/mach/hurd/sigsuspend.c b/sysdeps/mach/hurd/sigsuspend.c
+index 7e32472..2e55e30 100644
+--- a/sysdeps/mach/hurd/sigsuspend.c
++++ b/sysdeps/mach/hurd/sigsuspend.c
+@@ -1,5 +1,5 @@
+-/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002, 2007
+-     Free Software Foundation, Inc.
++/* Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2002, 2007,
++     2011 Free Software Foundation, Inc.
+ 
+    This file is part of the GNU C Library.
+ 
+@@ -43,7 +43,7 @@ __sigsuspend (set)
+ 
+   ss = _hurd_self_sigstate ();
+ 
+-  __spin_lock (&ss->lock);
++  _hurd_sigstate_lock (ss);
+ 
+   oldmask = ss->blocked;
+   if (set != NULL)
+@@ -51,11 +51,11 @@ __sigsuspend (set)
+     ss->blocked = newmask & ~_SIG_CANT_MASK;
+ 
+   /* Notice if any pending signals just became unblocked.  */
+-  pending = ss->pending & ~ss->blocked;
++  pending = _hurd_sigstate_pending (ss) & ~ss->blocked;
+ 
+   /* Tell the signal thread to message us when a signal arrives.  */
+   ss->suspended = wait;
+-  __spin_unlock (&ss->lock);
++  _hurd_sigstate_unlock (ss);
+ 
+   if (pending)
+     /* Tell the signal thread to check for pending signals.  */
+@@ -66,10 +66,11 @@ __sigsuspend (set)
+ 	      MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+   __mach_port_destroy (__mach_task_self (), wait);
+ 
+-  __spin_lock (&ss->lock);
+-  ss->blocked = oldmask;	/* Restore the old mask.  */
+-  pending = ss->pending & ~ss->blocked;	/* Again check for pending signals.  */
+-  __spin_unlock (&ss->lock);
++  /* Restore the old mask and check for pending signals again.  */
++  _hurd_sigstate_lock (ss);
++  ss->blocked = oldmask;
++  pending = _hurd_sigstate_pending(ss) & ~ss->blocked;
++  _hurd_sigstate_unlock (ss);
+ 
+   if (pending)
+     /* Tell the signal thread to check for pending signals.  */
+diff --git a/sysdeps/mach/hurd/sigwait.c b/sysdeps/mach/hurd/sigwait.c
+index 9794076..af50f74 100644
+--- a/sysdeps/mach/hurd/sigwait.c
++++ b/sysdeps/mach/hurd/sigwait.c
+@@ -1,4 +1,4 @@
+-/* Copyright (C) 1996,97,2001,02 Free Software Foundation, Inc.
++/* Copyright (C) 1996,97,2001,2002,2011 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
+@@ -28,7 +28,7 @@ int
+ __sigwait (const sigset_t *set, int *sig)
+ {
+   struct hurd_sigstate *ss;
+-  sigset_t mask, ready;
++  sigset_t mask, ready, blocked;
+   int signo = 0;
+   struct hurd_signal_preemptor preemptor;
+   jmp_buf buf;
+@@ -50,8 +50,8 @@ __sigwait (const sigset_t *set, int *sig)
+       /* Make sure this is all kosher */
+       assert (__sigismember (&mask, signo));
+ 
+-      /* Make sure this signal is unblocked */
+-      __sigdelset (&ss->blocked, signo);
++      /* Restore the blocking mask. */
++      ss->blocked = blocked;
+ 
+       return pe->handler;
+     }
+@@ -72,10 +72,11 @@ __sigwait (const sigset_t *set, int *sig)
+     __sigemptyset (&mask);
+ 
+   ss = _hurd_self_sigstate ();
+-  __spin_lock (&ss->lock);
++  _hurd_sigstate_lock (ss);
+ 
+   /* See if one of these signals is currently pending.  */
+-  __sigandset (&ready, &ss->pending, &mask);
++  sigset_t pending = _hurd_sigstate_pending (ss);
++  __sigandset (&ready, &pending, &mask);
+   if (! __sigisemptyset (&ready))
+     {
+       for (signo = 1; signo < NSIG; signo++)
+@@ -103,7 +104,11 @@ __sigwait (const sigset_t *set, int *sig)
+       preemptor.next = ss->preemptors;
+       ss->preemptors = &preemptor;
+ 
+-      __spin_unlock (&ss->lock);
++      /* Unblock the expected signals */
++      blocked = ss->blocked;
++      ss->blocked &= ~mask;
++
++      _hurd_sigstate_unlock (ss);
+ 
+       /* Wait. */
+       __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
+@@ -114,7 +119,7 @@ __sigwait (const sigset_t *set, int *sig)
+     {
+       assert (signo);
+ 
+-      __spin_lock (&ss->lock);
++      _hurd_sigstate_lock (ss);
+ 
+       /* Delete our preemptor. */
+       assert (ss->preemptors == &preemptor);
+@@ -123,7 +128,7 @@ __sigwait (const sigset_t *set, int *sig)
+ 
+ 
+ all_done:
+-  spin_unlock (&ss->lock);
++  _hurd_sigstate_unlock (ss);
+ 
+   __mach_port_destroy (__mach_task_self (), wait);
+   *sig = signo;
+diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
+index 244ca2d..373da8d 100644
+--- a/sysdeps/mach/hurd/spawni.c
++++ b/sysdeps/mach/hurd/spawni.c
+@@ -1,5 +1,5 @@
+ /* spawn a new process running an executable.  Hurd version.
+-   Copyright (C) 2001,02,04 Free Software Foundation, Inc.
++   Copyright (C) 2001,2002,2004,2011 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
+@@ -239,26 +239,29 @@ __spawni (pid_t *pid, const char *file,
+   assert (! __spin_lock_locked (&ss->critical_section_lock));
+   __spin_lock (&ss->critical_section_lock);
+ 
+-  __spin_lock (&ss->lock);
++  _hurd_sigstate_lock (ss);
+   ints[INIT_SIGMASK] = ss->blocked;
+-  ints[INIT_SIGPENDING] = ss->pending;
++  ints[INIT_SIGPENDING] = _hurd_sigstate_pending (ss); /* XXX really? */
+   ints[INIT_SIGIGN] = 0;
+   /* Unless we were asked to reset all handlers to SIG_DFL,
+      pass down the set of signals that were set to SIG_IGN.  */
+-  if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
+-    for (i = 1; i < NSIG; ++i)
+-      if (ss->actions[i].sa_handler == SIG_IGN)
+-	ints[INIT_SIGIGN] |= __sigmask (i);
+-
+-  /* We hold the sigstate lock until the exec has failed so that no signal
+-     can arrive between when we pack the blocked and ignored signals, and
+-     when the exec actually happens.  A signal handler could change what
++  {
++    struct sigaction *actions = _hurd_sigstate_actions (ss);
++    if ((flags & POSIX_SPAWN_SETSIGDEF) == 0)
++      for (i = 1; i < NSIG; ++i)
++	if (actions[i].sa_handler == SIG_IGN)
++	  ints[INIT_SIGIGN] |= __sigmask (i);
++  }
++
++  /* We hold the critical section lock until the exec has failed so that no
++     signal can arrive between when we pack the blocked and ignored signals,
++     and when the exec actually happens.  A signal handler could change what
+      signals are blocked and ignored.  Either the change will be reflected
+      in the exec, or the signal will never be delivered.  Setting the
+      critical section flag avoids anything we call trying to acquire the
+      sigstate lock.  */
+ 
+-  __spin_unlock (&ss->lock);
++  _hurd_sigstate_unlock (ss);
+ 
+   /* Set signal mask.  */
+   if ((flags & POSIX_SPAWN_SETSIGMASK) != 0)
diff --git a/debian/patches/series b/debian/patches/series
index 0616930..fa4cc3e 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -134,22 +134,24 @@ hurd-i386/unsubmitted-no-hp-timing.diff
 hurd-i386/submitted-catch-signal.diff
 hurd-i386/unsubmitted-sendmsg-SCM_RIGHTS.diff
 hurd-i386/cvs-header-prot.diff
 hurd-i386/cvs-psiginfo.diff
 hurd-i386/unsubmitted-ptsname.diff
 hurd-i386/cvs-if_freereq.diff
 hurd-i386/submitted-add-needed.diff
 hurd-i386/local-ED.diff
 hurd-i386/unsubmitted-pthread_posix-option.diff
 hurd-i386/local-madvise_warn.diff
-hurd-i386/submitted-PTRACE_CONTINUE.diff
 hurd-i386/submitted-ldsodefs.h.diff
+hurd-i386/submitted-hurdsig-fixes.diff
+hurd-i386/submitted-hurdsig-global-dispositions.diff
+hurd-i386/submitted-hurdsig-SA_SIGINFO.diff
 
 ia64/local-dlfptr.diff
 ia64/submitted-sysconf.diff
 ia64/submitted-libm.diff
 
 i386/local-biarch.diff
 i386/local-clone.diff
 i386/local-cmov.diff
 i386/local-cpuid-level2.diff
 i386/local-linuxthreads-gscope.diff
-- 
1.7.5.4


Reply to: