]> code.delx.au - gnu-emacs/blobdiff - src/sysdep.c
; Merge from origin/emacs-25
[gnu-emacs] / src / sysdep.c
index cb361ec2dc517ff59a9d7500ed2df8da43e14a36..e73acec733e6fc800c48e79a352d58875a4a7c27 100644 (file)
@@ -1,5 +1,5 @@
 /* Interfaces to system-dependent kernel and library entries.
-   Copyright (C) 1985-1988, 1993-1995, 1999-2015 Free Software
+   Copyright (C) 1985-1988, 1993-1995, 1999-2016 Free Software
    Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -79,9 +79,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "msdos.h"
 #endif
 
-#ifdef HAVE_SYS_RESOURCE_H
-#include <sys/resource.h>
-#endif
 #include <sys/param.h>
 #include <sys/file.h>
 #include <fcntl.h>
@@ -96,13 +93,11 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "keyboard.h"
 #include "frame.h"
-#include "window.h"
 #include "termhooks.h"
 #include "termchar.h"
 #include "termopts.h"
-#include "dispextern.h"
 #include "process.h"
-#include "cm.h"  /* for reset_sys_modes */
+#include "cm.h"
 
 #ifdef WINDOWSNT
 #include <direct.h>
@@ -662,14 +657,6 @@ unrequest_sigio (void)
   interrupts_deferred = 1;
 #endif
 }
-
-void
-ignore_sigio (void)
-{
-#ifdef USABLE_SIGIO
-  signal (SIGIO, SIG_IGN);
-#endif
-}
 \f
 #ifndef MSDOS
 /* Block SIGCHLD.  */
@@ -1623,16 +1610,63 @@ handle_arith_signal (int sig)
   xsignal0 (Qarith_error);
 }
 
-#ifdef HAVE_STACK_OVERFLOW_HANDLING
-
-/* -1 if stack grows down as expected on most OS/ABI variants, 1 otherwise.  */
-
-static int stack_direction;
+#if defined HAVE_STACK_OVERFLOW_HANDLING && !defined WINDOWSNT
 
 /* Alternate stack used by SIGSEGV handler below.  */
 
 static unsigned char sigsegv_stack[SIGSTKSZ];
 
+
+/* Return true if SIGINFO indicates a stack overflow.  */
+
+static bool
+stack_overflow (siginfo_t *siginfo)
+{
+  if (!attempt_stack_overflow_recovery)
+    return false;
+
+  /* In theory, a more-accurate heuristic can be obtained by using
+     GNU/Linux pthread_getattr_np along with POSIX pthread_attr_getstack
+     and pthread_attr_getguardsize to find the location and size of the
+     guard area.  In practice, though, these functions are so hard to
+     use reliably that they're not worth bothering with.  E.g., see:
+     https://sourceware.org/bugzilla/show_bug.cgi?id=16291
+     Other operating systems also have problems, e.g., Solaris's
+     stack_violation function is tailor-made for this problem, but it
+     doesn't work on Solaris 11.2 x86-64 with a 32-bit executable.
+
+     GNU libsigsegv is overkill for Emacs; otherwise it might be a
+     candidate here.  */
+
+  if (!siginfo)
+    return false;
+
+  /* The faulting address.  */
+  char *addr = siginfo->si_addr;
+  if (!addr)
+    return false;
+
+  /* The known top and bottom of the stack.  The actual stack may
+     extend a bit beyond these boundaries.  */
+  char *bot = stack_bottom;
+  char *top = near_C_stack_top ();
+
+  /* Log base 2 of the stack heuristic ratio.  This ratio is the size
+     of the known stack divided by the size of the guard area past the
+     end of the stack top.  The heuristic is that a bad address is
+     considered to be a stack overflow if it occurs within
+     stacksize>>LG_STACK_HEURISTIC bytes above the top of the known
+     stack.  This heuristic is not exactly correct but it's good
+     enough in practice.  */
+  enum { LG_STACK_HEURISTIC = 8 };
+
+  if (bot < top)
+    return 0 <= addr - top && addr - top < (top - bot) >> LG_STACK_HEURISTIC;
+  else
+    return 0 <= top - addr && top - addr < (bot - top) >> LG_STACK_HEURISTIC;
+}
+
+
 /* Attempt to recover from SIGSEGV caused by C stack overflow.  */
 
 static void
@@ -1640,28 +1674,15 @@ handle_sigsegv (int sig, siginfo_t *siginfo, void *arg)
 {
   /* Hard GC error may lead to stack overflow caused by
      too nested calls to mark_object.  No way to survive.  */
-  if (!gc_in_progress)
-    {
-      struct rlimit rlim;
+  bool fatal = gc_in_progress;
 
-      if (!getrlimit (RLIMIT_STACK, &rlim))
-       {
-         enum { STACK_DANGER_ZONE = 16 * 1024 };
-         char *beg, *end, *addr;
-
-         beg = stack_bottom;
-         end = stack_bottom + stack_direction * rlim.rlim_cur;
-         if (beg > end)
-           addr = beg, beg = end, end = addr;
-         addr = (char *) siginfo->si_addr;
-         /* If we're somewhere on stack and too close to
-            one of its boundaries, most likely this is it.  */
-         if (beg < addr && addr < end
-             && (addr - beg < STACK_DANGER_ZONE
-                 || end - addr < STACK_DANGER_ZONE))
-           siglongjmp (return_to_command_loop, 1);
-       }
-    }
+#ifdef FORWARD_SIGNAL_TO_MAIN_THREAD
+  if (!fatal && !pthread_equal (pthread_self (), main_thread))
+    fatal = true;
+#endif
+
+  if (!fatal && stack_overflow (siginfo))
+    siglongjmp (return_to_command_loop, 1);
 
   /* Otherwise we can't do anything with this.  */
   deliver_fatal_thread_signal (sig);
@@ -1676,8 +1697,6 @@ init_sigsegv (void)
   struct sigaction sa;
   stack_t ss;
 
-  stack_direction = ((char *) &ss < stack_bottom) ? -1 : 1;
-
   ss.ss_sp = sigsegv_stack;
   ss.ss_size = sizeof (sigsegv_stack);
   ss.ss_flags = 0;
@@ -1690,7 +1709,7 @@ init_sigsegv (void)
   return sigaction (SIGSEGV, &sa, NULL) < 0 ? 0 : 1;
 }
 
-#else /* not HAVE_STACK_OVERFLOW_HANDLING */
+#else /* not HAVE_STACK_OVERFLOW_HANDLING or WINDOWSNT */
 
 static bool
 init_sigsegv (void)
@@ -1698,7 +1717,7 @@ init_sigsegv (void)
   return 0;
 }
 
-#endif /* HAVE_STACK_OVERFLOW_HANDLING */
+#endif /* HAVE_STACK_OVERFLOW_HANDLING && !WINDOWSNT */
 
 static void
 deliver_arith_signal (int sig)
@@ -2174,6 +2193,14 @@ emacs_backtrace (int backtrace_limit)
   else
     {
       buffer = main_backtrace_buffer;
+
+      /* Work around 'backtrace' bug; see Bug#19959 and glibc bug#18084.  */
+      if (bounded_limit < 0)
+       {
+         backtrace (buffer, 1);
+         return;
+       }
+
       npointers = backtrace (buffer, bounded_limit + 1);
     }
 
@@ -2693,10 +2720,8 @@ Lisp_Object
 list_system_processes (void)
 {
   Lisp_Object procdir, match, proclist, next;
-  struct gcpro gcpro1, gcpro2;
-  register Lisp_Object tail;
+  Lisp_Object tail;
 
-  GCPRO2 (procdir, match);
   /* For every process on the system, there's a directory in the
      "/proc" pseudo-directory whose name is the numeric ID of that
      process.  */
@@ -2711,7 +2736,6 @@ list_system_processes (void)
       next = XCDR (tail);
       XSETCAR (tail, Fstring_to_number (XCAR (tail), Qnil));
     }
-  UNGCPRO;
 
   /* directory_files_internal returns the files in reverse order; undo
      that.  */
@@ -2733,7 +2757,6 @@ list_system_processes (void)
   struct kinfo_proc *procs;
   size_t i;
 
-  struct gcpro gcpro1;
   Lisp_Object proclist = Qnil;
 
   if (sysctl (mib, 3, NULL, &len, NULL, 0) != 0)
@@ -2746,7 +2769,6 @@ list_system_processes (void)
       return proclist;
     }
 
-  GCPRO1 (proclist);
   len /= sizeof (struct kinfo_proc);
   for (i = 0; i < len; i++)
     {
@@ -2756,7 +2778,6 @@ list_system_processes (void)
       proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist);
 #endif
     }
-  UNGCPRO;
 
   xfree (procs);
 
@@ -2967,7 +2988,6 @@ system_process_attributes (Lisp_Object pid)
   Lisp_Object attrs = Qnil;
   Lisp_Object cmd_str, decoded_cmd;
   ptrdiff_t count;
-  struct gcpro gcpro1, gcpro2;
 
   CHECK_NUMBER_OR_FLOAT (pid);
   CONS_TO_INTEGER (pid, pid_t, proc_id);
@@ -2975,8 +2995,6 @@ system_process_attributes (Lisp_Object pid)
   if (stat (procfn, &st) < 0)
     return attrs;
 
-  GCPRO2 (attrs, decoded_cmd);
-
   /* euid egid */
   uid = st.st_uid;
   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
@@ -3165,7 +3183,6 @@ system_process_attributes (Lisp_Object pid)
       attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
     }
 
-  UNGCPRO;
   return attrs;
 }
 
@@ -3204,7 +3221,6 @@ system_process_attributes (Lisp_Object pid)
   gid_t gid;
   Lisp_Object attrs = Qnil;
   Lisp_Object decoded_cmd;
-  struct gcpro gcpro1, gcpro2;
   ptrdiff_t count;
 
   CHECK_NUMBER_OR_FLOAT (pid);
@@ -3213,8 +3229,6 @@ system_process_attributes (Lisp_Object pid)
   if (stat (procfn, &st) < 0)
     return attrs;
 
-  GCPRO2 (attrs, decoded_cmd);
-
   /* euid egid */
   uid = st.st_uid;
   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (uid)), attrs);
@@ -3307,7 +3321,6 @@ system_process_attributes (Lisp_Object pid)
       attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs);
     }
   unbind_to (count, Qnil);
-  UNGCPRO;
   return attrs;
 }
 
@@ -3343,7 +3356,6 @@ system_process_attributes (Lisp_Object pid)
   struct kinfo_proc proc;
   size_t proclen = sizeof proc;
 
-  struct gcpro gcpro1, gcpro2;
   Lisp_Object attrs = Qnil;
   Lisp_Object decoded_comm;
 
@@ -3354,8 +3366,6 @@ system_process_attributes (Lisp_Object pid)
   if (sysctl (mib, 4, &proc, &proclen, NULL, 0) != 0)
     return attrs;
 
-  GCPRO2 (attrs, decoded_comm);
-
   attrs = Fcons (Fcons (Qeuid, make_fixnum_or_float (proc.ki_uid)), attrs);
 
   block_input ();
@@ -3493,7 +3503,6 @@ system_process_attributes (Lisp_Object pid)
       attrs = Fcons (Fcons (Qargs, decoded_comm), attrs);
     }
 
-  UNGCPRO;
   return attrs;
 }