New module 'uninorm/decomposing-form'.
[gnulib.git] / lib / c-stack.c
index 11cb9ef..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);
 }
@@ -317,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);
 }