New module 'unicase/u16-ct-totitle'.
[gnulib.git] / lib / c-stack.c
index 6802665..d260b47 100644 (file)
@@ -1,6 +1,7 @@
 /* Stack overflow handling.
 
-   Copyright (C) 2002, 2004, 2006, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2004, 2006, 2008, 2009 Free Software
+   Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -67,9 +68,6 @@ typedef struct sigaltstack stack_t;
 #endif
 
 #include <unistd.h>
-#ifndef STDERR_FILENO
-# define STDERR_FILENO 2
-#endif
 
 #if HAVE_LIBSIGSEGV
 # include <sigsegv.h>
@@ -82,6 +80,9 @@ typedef struct sigaltstack stack_t;
 # define SIGACTION_WORKS 1
 #else
 # define SIGACTION_WORKS 0
+# ifndef SA_ONSTACK
+#  define SA_ONSTACK 0
+# endif
 #endif
 
 extern char *program_name;
@@ -238,21 +239,21 @@ segv_handler (int signo, siginfo_t *info,
              void *context __attribute__ ((unused)))
 {
   /* Clear SIGNO if it seems to have been a stack overflow.  */
-  if (0 < info->si_code)
-    {
 #  if ! HAVE_XSI_STACK_OVERFLOW_HEURISTIC
-      /* We can't easily determine whether it is a stack overflow; so
-        assume that the rest of our program is perfect (!) and that
-        this segmentation violation is a stack overflow.
-
-        Note that although both Linux and Solaris provide
-        sigaltstack, SA_ONSTACK, and SA_SIGINFO, currently only
-        Solaris satisfies the XSI heueristic.  This is because
-        Solaris populates uc_stack with the details of the
-        interrupted stack, while Linux populates it with the details
-        of the current stack.  */
-      signo = 0;
+  /* We can't easily determine whether it is a stack overflow; so
+     assume that the rest of our program is perfect (!) and that
+     this segmentation violation is a stack overflow.
+
+     Note that although both Linux and Solaris provide
+     sigaltstack, SA_ONSTACK, and SA_SIGINFO, currently only
+     Solaris satisfies the XSI heueristic.  This is because
+     Solaris populates uc_stack with the details of the
+     interrupted stack, while Linux populates it with the details
+     of the current stack.  */
+  signo = 0;
 #  else
+  if (0 < info->si_code)
+    {
       /* If the faulting address is within the stack, or within one
         page of the stack end, assume that it is a stack
         overflow.  */
@@ -277,8 +278,8 @@ segv_handler (int signo, siginfo_t *info,
        write (STDERR_FILENO, buf, strlen (buf));
       }
 #   endif
-#  endif
     }
+#  endif
 
   die (signo);
 }
@@ -291,8 +292,15 @@ c_stack_action (void (*action) (int))
   stack_t st;
   struct sigaction act;
   st.ss_flags = 0;
+# if SIGALTSTACK_SS_REVERSED
+  /* Irix mistakenly treats ss_sp as the upper bound, rather than
+     lower bound, of the alternate stack.  */
+  st.ss_sp = alternate_signal_stack.buffer + SIGSTKSZ - sizeof (void *);
+  st.ss_size = sizeof alternate_signal_stack.buffer - sizeof (void *);
+# else
   st.ss_sp = alternate_signal_stack.buffer;
   st.ss_size = sizeof alternate_signal_stack.buffer;
+# endif
   r = sigaltstack (&st, NULL);
   if (r != 0)
     return r;
@@ -310,10 +318,14 @@ c_stack_action (void (*action) (int))
   act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
   act.sa_sigaction = segv_handler;
 # else
-  act.sa_flags = SA_NODEFER | SA_RESETHAND;
+  act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND;
   act.sa_handler = die;
 # endif
 
+# if FAULT_YIELDS_SIGBUS
+  if (sigaction (SIGBUS, &act, NULL) < 0)
+    return -1;
+# endif
   return sigaction (SIGSEGV, &act, NULL);
 }