This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 15/15] Hurd signals: Use POSIX sigcodes


On Thu, Jun 30, 2011 at 12:27:51AM +0200, Samuel Thibault wrote:
> Jeremie Koenig, le Wed 29 Jun 2011 18:30:27 +0200, a écrit :
> > * sysdeps/mach/hurd/i386/bits/sigcontext.h: Remove the constants formerly
> > used as sigcodes.
> 
> I don't think you can do that. I'm afraid you need to keep both the old
> values for the !SA_SIGINFO case and the POSIX values for the SA_SIGINFO
> case.

I attach two alternative patches (they built but I did not test them).

Both of them use two variants of _hurd_exception2signal and call the
non-default variant from trampoline.c when it's required. Non-exception
sigcodes are cleared to 0 in the legacy case, in both patches.

I personally favor "sigcodes_legacy_as_old.diff" since I believe we
should eventually phase out and get rid of the legacy sigcodes.

-- 
Jeremie Koenig <jk@jk.fr.eu.org>
http://jk.fr.eu.org
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
@@ -247,40 +247,45 @@ _hurd_critical_section_unlock (void *our_lock)
    Arguments give the "init ints" from exec_startup.  */
 
 extern void _hurdsig_init (const int *intarray, size_t intarraysize);
 
 /* Initialize proc server-assisted fault recovery for the signal thread.  */
 
 extern void _hurdsig_fault_init (void);
 
 /* Raise a signal as described by SIGNO an DETAIL, on the thread whose
    sigstate SS points to.  If SS is a null pointer, this instead affects
    the calling thread.  */
 
 extern void _hurd_raise_signal (struct hurd_sigstate *ss, int signo,
 				const struct hurd_signal_detail *detail);
 
 /* Translate a Mach exception into a signal (machine-dependent).  */
 
 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
    as the stop signal unless UNTRACED is nonzero.  When the signal can be
    considered delivered, sends a sig_post reply message on REPLY_PORT
    indicating success.  SS is not locked.  */
 
 extern 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);
 
 /* Set up STATE and SS to handle signal SIGNO by running HANDLER.  If
    RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to
    finish before running the signal handler.  The handler is passed SIGNO,
    SIGCODE, and the returned `struct sigcontext' (which resides on the
    stack the handler will use, and which describes the state of the thread
    encoded in STATE before running the handler).  */
diff --git a/hurd/hurdinit.c b/hurd/hurdinit.c
index 259f8a3..97d3460 100644
--- a/hurd/hurdinit.c
+++ b/hurd/hurdinit.c
@@ -159,41 +159,41 @@ _hurd_new_proc_init (char **argv,
   _hurdsig_fault_init ();
 
   /* Call other things which want to do some initialization.  These are not
      on the _hurd_subinit hook because things there assume that things done
      here, like _hurd_pid, are already initialized.  */
   RUN_HOOK (_hurd_proc_subinit, ());
 
   /* XXX This code should probably be removed entirely at some point.  This
      conditional should make it reasonably usable with old gdb's for a
      while.  Eventually it probably makes most sense for the exec server to
      mask out EXEC_SIGTRAP so the debugged program is closer to not being
      able to tell it's being debugged.  */
   if (!__sigisemptyset (&_hurdsig_traced)
 #ifdef EXEC_SIGTRAP
       && !(_hurd_exec_flags & EXEC_SIGTRAP)
 #endif
       )
     /* 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>
 versioned_symbol (libc, _hurd_new_proc_init, _hurd_proc_init, GLIBC_2_1);
 
 /* Called when we get a message telling us to change our proc server port.  */
 
 error_t
 _hurd_setproc (process_t procserver)
 {
   error_t err;
   mach_port_t oldmsg;
 
   /* Give the proc server our message port.  */
   if (err = __proc_setmsgport (procserver, _hurd_msgport, &oldmsg))
     return err;
   if (oldmsg != MACH_PORT_NULL)
     /* Deallocate the old msg port we replaced.  */
     __mach_port_deallocate (__mach_task_self (), oldmsg);
 
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
@@ -79,40 +79,44 @@ struct sigcontext
     int sc_uesp;		/* This stack pointer is used.  */
     int sc_ss;			/* Stack segment register.  */
 
     /* Following mimics struct i386_float_state.  Structures and symbolic
        values can be found in <mach/i386/fp_reg.h>.  */
 #define sc_i386_float_state sc_fpkind
     int sc_fpkind;		/* FP_NO, FP_387, etc.  */
     int sc_fpused;		/* If zero, ignore rest of float state.  */
     struct i386_fp_save sc_fpsave;
     struct i386_fp_regs sc_fpregs;
     int sc_fpexcsr;		/* FPSR including exception bits.  */
   };
 
 /* Traditional BSD names for some members.  */
 #define sc_sp	sc_uesp		/* Stack pointer.  */
 #define sc_fp	sc_ebp		/* Frame pointer.  */
 #define sc_pc	sc_eip		/* Process counter.  */
 #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 */
 #define FPE_FLTOVF_FAULT	0x3 /* floating overflow */
 #define FPE_FLTDIV_FAULT	0x4 /* floating divide by zero */
 #define FPE_FLTUND_FAULT	0x5 /* floating underflow */
 #define FPE_SUBRNG_FAULT	0x7 /* BOUNDS instruction failed */
 #define FPE_FLTDNR_FAULT	0x8 /* denormalized operand */
 #define FPE_FLTINX_FAULT	0x9 /* floating loss of precision */
 #define FPE_EMERR_FAULT		0xa /* mysterious emulation error 33 */
 #define FPE_EMBND_FAULT		0xb /* emulation BOUNDS instruction failed */
 
 /* Codes for SIGILL.  */
 #define ILL_INVOPR_FAULT	0x1 /* invalid operation */
 #define ILL_STACK_FAULT		0x2 /* fault on microkernel stack access */
 #define ILL_FPEOPR_FAULT	0x3 /* invalid floating operation */
 
 /* Codes for SIGTRAP.  */
 #define DBG_SINGLE_TRAP		0x1 /* single step */
 #define DBG_BRKPNT_FAULT	0x2 /* breakpoint instruction */
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
@@ -7,160 +7,191 @@
    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.  */
 
 #include <hurd.h>
 #include <hurd/signal.h>
 #include <mach/exception.h>
 
 /* 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;
 
   switch (detail->exc)
     {
     default:
       *signo = SIGIOT;
       detail->code = detail->exc;
       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;
 
 	case EXC_I386_EXTERR:
 	  /* Subcode is the fp_status word saved by the hardware.
 	     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;
 
     case EXC_EMULATION:
       /* 3.0 doesn't give this one, why, I don't know.  */
       *signo = SIGEMT;
       detail->code = 0;
       break;
 
     case EXC_SOFTWARE:
       /* The only time we get this in Mach 3.0
 	 is for an out of bounds trap.  */
       if (detail->exc_code == EXC_I386_BOUND)
 	{
 	  *signo = SIGFPE;
-	  detail->code = FPE_SUBRNG_FAULT;
+	  detail->code = posix ? FPE_FLTSUB : FPE_SUBRNG_FAULT;
 	}
       else
 	{
 	  *signo = SIGEMT;
 	  detail->code = 0;
 	}
       break;
 
     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 0d2660d..5abd33d 100644
--- a/sysdeps/mach/hurd/i386/trampoline.c
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -225,40 +225,49 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
       memcpy (&scp->sc_i386_thread_state,
 	      &state->basic, sizeof (state->basic));
 
       /* struct sigcontext is laid out so that starting at sc_fpkind mimics
 	 a struct i386_float_state.  */
       ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE,
 			      &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)
 	return NULL;
     }
 
   /* Modify the thread state to call the trampoline code on the new stack.  */
   if (rpc_wait)
     {
       /* The signalee thread was blocked in a mach_msg_trap system call,
 	 still waiting for a reply.  We will have it run the special
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
@@ -48,41 +48,41 @@ __kill (pid_t pid, int sig)
 	   get MIG_SERVER_DIED.  */
 	do
 	  {
 	    task_t refport;
 	    err = __proc_pid2task (proc, pid, &refport);
 	    /* Ignore zombies.  */
 	    if (!err && refport != MACH_PORT_NULL)
 	      {
 		err = __task_terminate (refport);
 		__mach_port_deallocate (__mach_task_self (), refport);
 	      }
 	  } while (err == MACH_SEND_INVALID_DEST ||
 		   err == MIG_SERVER_DIED);
       else
 	{
 	  error_t taskerr;
 	  error_t kill_port (mach_port_t msgport, mach_port_t refport)
 	    {
 	      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.  */
 
 	      if (taskerr)
 		/* If we could not get the task port, we can do nothing.  */
 		return taskerr;
 
 	      if (refport == MACH_PORT_NULL)
 		/* proc_pid2task returned success with a null task port.
 		   That means the process is a zombie.  Signals
 		   to zombies should return success and do nothing.  */
 		return 0;
 
 	      /* For user convenience in the case of a task that has
 		 not registered any message port with the proc server,
 		 translate a few signals to direct task operations.  */
 	      switch (sig)
 		{
 		  /* The only signals that really make sense for an
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
@@ -88,41 +88,41 @@ timer_thread (void)
 	 the receive timeout.  Notice interrupts so that if we are
 	 thread_abort'd, we will loop around and fetch new values from
 	 _hurd_itimerval.  */
       err = __mach_msg (&msg.header,
 			MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
 			0, 0, _hurd_itimer_port,
 			_hurd_itimerval.it_value.tv_sec * 1000 +
 			_hurd_itimerval.it_value.tv_usec / 1000,
 			MACH_PORT_NULL);
       switch (err)
 	{
 	case MACH_RCV_TIMED_OUT:
 	  /* We got the expected timeout.  Send a message to the signal
 	     thread to tell it to post a SIGALRM signal.  We use
 	     _hurd_itimer_port as the reply port just so we will block until
 	     the signal thread has frobnicated things to reload the itimer or
 	     has terminated this thread.  */
 	  __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:
 	  /* We were thread_abort'd.  This is to tell us that
 	     _hurd_itimerval has changed and we need to reexamine it
 	     and start waiting with the new timeout value.  */
 	  break;
 
 	case MACH_MSG_SUCCESS:
 	  /* We got the reply message from the sig_post_request above.
 	     Ignore it and reexamine the timer value.  */
 	  __mach_msg_destroy (&msg.header); /* Just in case.  */
 	  break;
 
 	default:
 	  /* Unexpected lossage.  Oh well, keep trying.  */
 	  break;
 	}
     }
 }
diff --git a/hurd/hurd/signal.h b/hurd/hurd/signal.h
index 1c4733a..a98ee40 100644
--- a/hurd/hurd/signal.h
+++ b/hurd/hurd/signal.h
@@ -247,40 +247,45 @@ _hurd_critical_section_unlock (void *our_lock)
    Arguments give the "init ints" from exec_startup.  */
 
 extern void _hurdsig_init (const int *intarray, size_t intarraysize);
 
 /* Initialize proc server-assisted fault recovery for the signal thread.  */
 
 extern void _hurdsig_fault_init (void);
 
 /* Raise a signal as described by SIGNO an DETAIL, on the thread whose
    sigstate SS points to.  If SS is a null pointer, this instead affects
    the calling thread.  */
 
 extern void _hurd_raise_signal (struct hurd_sigstate *ss, int signo,
 				const struct hurd_signal_detail *detail);
 
 /* Translate a Mach exception into a signal (machine-dependent).  */
 
 extern void _hurd_exception2signal (struct hurd_signal_detail *detail,
 				    int *signo);
 
+/* Translate a Mach exception into a signal with a POSIX sigcode.  */
+
+extern void _hurd_exception2signal_posix (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
    as the stop signal unless UNTRACED is nonzero.  When the signal can be
    considered delivered, sends a sig_post reply message on REPLY_PORT
    indicating success.  SS is not locked.  */
 
 extern 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);
 
 /* Set up STATE and SS to handle signal SIGNO by running HANDLER.  If
    RPC_WAIT is nonzero, the thread needs to wait for a pending RPC to
    finish before running the signal handler.  The handler is passed SIGNO,
    SIGCODE, and the returned `struct sigcontext' (which resides on the
    stack the handler will use, and which describes the state of the thread
    encoded in STATE before running the handler).  */
diff --git a/hurd/hurdinit.c b/hurd/hurdinit.c
index 259f8a3..97d3460 100644
--- a/hurd/hurdinit.c
+++ b/hurd/hurdinit.c
@@ -159,41 +159,41 @@ _hurd_new_proc_init (char **argv,
   _hurdsig_fault_init ();
 
   /* Call other things which want to do some initialization.  These are not
      on the _hurd_subinit hook because things there assume that things done
      here, like _hurd_pid, are already initialized.  */
   RUN_HOOK (_hurd_proc_subinit, ());
 
   /* XXX This code should probably be removed entirely at some point.  This
      conditional should make it reasonably usable with old gdb's for a
      while.  Eventually it probably makes most sense for the exec server to
      mask out EXEC_SIGTRAP so the debugged program is closer to not being
      able to tell it's being debugged.  */
   if (!__sigisemptyset (&_hurdsig_traced)
 #ifdef EXEC_SIGTRAP
       && !(_hurd_exec_flags & EXEC_SIGTRAP)
 #endif
       )
     /* 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>
 versioned_symbol (libc, _hurd_new_proc_init, _hurd_proc_init, GLIBC_2_1);
 
 /* Called when we get a message telling us to change our proc server port.  */
 
 error_t
 _hurd_setproc (process_t procserver)
 {
   error_t err;
   mach_port_t oldmsg;
 
   /* Give the proc server our message port.  */
   if (err = __proc_setmsgport (procserver, _hurd_msgport, &oldmsg))
     return err;
   if (oldmsg != MACH_PORT_NULL)
     /* Deallocate the old msg port we replaced.  */
     __mach_port_deallocate (__mach_task_self (), oldmsg);
 
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
@@ -79,40 +79,44 @@ struct sigcontext
     int sc_uesp;		/* This stack pointer is used.  */
     int sc_ss;			/* Stack segment register.  */
 
     /* Following mimics struct i386_float_state.  Structures and symbolic
        values can be found in <mach/i386/fp_reg.h>.  */
 #define sc_i386_float_state sc_fpkind
     int sc_fpkind;		/* FP_NO, FP_387, etc.  */
     int sc_fpused;		/* If zero, ignore rest of float state.  */
     struct i386_fp_save sc_fpsave;
     struct i386_fp_regs sc_fpregs;
     int sc_fpexcsr;		/* FPSR including exception bits.  */
   };
 
 /* Traditional BSD names for some members.  */
 #define sc_sp	sc_uesp		/* Stack pointer.  */
 #define sc_fp	sc_ebp		/* Frame pointer.  */
 #define sc_pc	sc_eip		/* Process counter.  */
 #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 */
 #define FPE_FLTOVF_FAULT	0x3 /* floating overflow */
 #define FPE_FLTDIV_FAULT	0x4 /* floating divide by zero */
 #define FPE_FLTUND_FAULT	0x5 /* floating underflow */
 #define FPE_SUBRNG_FAULT	0x7 /* BOUNDS instruction failed */
 #define FPE_FLTDNR_FAULT	0x8 /* denormalized operand */
 #define FPE_FLTINX_FAULT	0x9 /* floating loss of precision */
 #define FPE_EMERR_FAULT		0xa /* mysterious emulation error 33 */
 #define FPE_EMBND_FAULT		0xb /* emulation BOUNDS instruction failed */
 
 /* Codes for SIGILL.  */
 #define ILL_INVOPR_FAULT	0x1 /* invalid operation */
 #define ILL_STACK_FAULT		0x2 /* fault on microkernel stack access */
 #define ILL_FPEOPR_FAULT	0x3 /* invalid floating operation */
 
 /* Codes for SIGTRAP.  */
 #define DBG_SINGLE_TRAP		0x1 /* single step */
 #define DBG_BRKPNT_FAULT	0x2 /* breakpoint instruction */
diff --git a/sysdeps/mach/hurd/i386/exc2signal.c b/sysdeps/mach/hurd/i386/exc2signal.c
index a6bf750..1ad24bb 100644
--- a/sysdeps/mach/hurd/i386/exc2signal.c
+++ b/sysdeps/mach/hurd/i386/exc2signal.c
@@ -7,160 +7,191 @@
    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.  */
 
 #include <hurd.h>
 #include <hurd/signal.h>
 #include <mach/exception.h>
 
 /* 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;
 
   switch (detail->exc)
     {
     default:
       *signo = SIGIOT;
       detail->code = detail->exc;
       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;
 
 	case EXC_I386_EXTERR:
 	  /* Subcode is the fp_status word saved by the hardware.
 	     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;
 
     case EXC_EMULATION:
       /* 3.0 doesn't give this one, why, I don't know.  */
       *signo = SIGEMT;
       detail->code = 0;
       break;
 
     case EXC_SOFTWARE:
       /* The only time we get this in Mach 3.0
 	 is for an out of bounds trap.  */
       if (detail->exc_code == EXC_I386_BOUND)
 	{
 	  *signo = SIGFPE;
-	  detail->code = FPE_SUBRNG_FAULT;
+	  detail->code = posix ? FPE_FLTSUB : FPE_SUBRNG_FAULT;
 	}
       else
 	{
 	  *signo = SIGEMT;
 	  detail->code = 0;
 	}
       break;
 
     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, 0);
+}
+
+void
+_hurd_exception2signal_posix (struct hurd_signal_detail *detail, int *signo)
+{
+  exception2signal (detail, signo, 1);
+}
+
diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
index 0d2660d..bc8b1d0 100644
--- a/sysdeps/mach/hurd/i386/trampoline.c
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -218,48 +218,57 @@ _hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
       /* 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
 	 struct i386_thread_state.  */
       memcpy (&scp->sc_i386_thread_state,
 	      &state->basic, sizeof (state->basic));
 
       /* struct sigcontext is laid out so that starting at sc_fpkind mimics
 	 a struct i386_float_state.  */
       ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE,
 			      &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)
 	{
+	  /* Use POSIX exception sigcodes.  */
+	  if (detail->exc)
+	    {
+	      int nsigno;
+	      _hurd_exception2signal_posix (detail, &nsigno);
+	      assert (nsigno == signo);
+	    }
+
 	  stackframe->posix.siginfop = &stackframe->siginfo;
 	  stackframe->posix.uctxp = &stackframe->ucontext;
 	  fill_siginfo (&stackframe->siginfo, signo, detail, state);
 	  fill_ucontext (&stackframe->ucontext, scp);
 	}
       else
 	{
-	  stackframe->legacy.sigcode = detail->code;
+	  /* Clear sigcodes which don't originate from exceptions.  */
+	  stackframe->legacy.sigcode = detail->exc ? detail->code : 0;
 	  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)
 	return NULL;
     }
 
   /* Modify the thread state to call the trampoline code on the new stack.  */
   if (rpc_wait)
     {
       /* The signalee thread was blocked in a mach_msg_trap system call,
 	 still waiting for a reply.  We will have it run the special
 	 trampoline code which retries the message receive before running
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
@@ -48,41 +48,41 @@ __kill (pid_t pid, int sig)
 	   get MIG_SERVER_DIED.  */
 	do
 	  {
 	    task_t refport;
 	    err = __proc_pid2task (proc, pid, &refport);
 	    /* Ignore zombies.  */
 	    if (!err && refport != MACH_PORT_NULL)
 	      {
 		err = __task_terminate (refport);
 		__mach_port_deallocate (__mach_task_self (), refport);
 	      }
 	  } while (err == MACH_SEND_INVALID_DEST ||
 		   err == MIG_SERVER_DIED);
       else
 	{
 	  error_t taskerr;
 	  error_t kill_port (mach_port_t msgport, mach_port_t refport)
 	    {
 	      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.  */
 
 	      if (taskerr)
 		/* If we could not get the task port, we can do nothing.  */
 		return taskerr;
 
 	      if (refport == MACH_PORT_NULL)
 		/* proc_pid2task returned success with a null task port.
 		   That means the process is a zombie.  Signals
 		   to zombies should return success and do nothing.  */
 		return 0;
 
 	      /* For user convenience in the case of a task that has
 		 not registered any message port with the proc server,
 		 translate a few signals to direct task operations.  */
 	      switch (sig)
 		{
 		  /* The only signals that really make sense for an
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
@@ -88,41 +88,41 @@ timer_thread (void)
 	 the receive timeout.  Notice interrupts so that if we are
 	 thread_abort'd, we will loop around and fetch new values from
 	 _hurd_itimerval.  */
       err = __mach_msg (&msg.header,
 			MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
 			0, 0, _hurd_itimer_port,
 			_hurd_itimerval.it_value.tv_sec * 1000 +
 			_hurd_itimerval.it_value.tv_usec / 1000,
 			MACH_PORT_NULL);
       switch (err)
 	{
 	case MACH_RCV_TIMED_OUT:
 	  /* We got the expected timeout.  Send a message to the signal
 	     thread to tell it to post a SIGALRM signal.  We use
 	     _hurd_itimer_port as the reply port just so we will block until
 	     the signal thread has frobnicated things to reload the itimer or
 	     has terminated this thread.  */
 	  __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:
 	  /* We were thread_abort'd.  This is to tell us that
 	     _hurd_itimerval has changed and we need to reexamine it
 	     and start waiting with the new timeout value.  */
 	  break;
 
 	case MACH_MSG_SUCCESS:
 	  /* We got the reply message from the sig_post_request above.
 	     Ignore it and reexamine the timer value.  */
 	  __mach_msg_destroy (&msg.header); /* Just in case.  */
 	  break;
 
 	default:
 	  /* Unexpected lossage.  Oh well, keep trying.  */
 	  break;
 	}
     }
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]