X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/63efa6c6a559a23be863cad0c08457a2d29a0a67..e6013e8c8f3de0ca39c17a2da95346b4a320e6d0:/src/sysdep.c diff --git a/src/sysdep.c b/src/sysdep.c index a2bda96192..836cc271b1 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -79,9 +79,6 @@ along with GNU Emacs. If not, see . */ #include "msdos.h" #endif -#ifdef HAVE_SYS_RESOURCE_H -#include -#endif #include #include #include @@ -662,14 +659,6 @@ unrequest_sigio (void) interrupts_deferred = 1; #endif } - -void -ignore_sigio (void) -{ -#ifdef USABLE_SIGIO - signal (SIGIO, SIG_IGN); -#endif -} #ifndef MSDOS /* Block SIGCHLD. */ @@ -1623,16 +1612,60 @@ 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) +{ + /* 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 +1673,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 +1696,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 +1708,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 +1716,7 @@ init_sigsegv (void) return 0; } -#endif /* HAVE_STACK_OVERFLOW_HANDLING */ +#endif /* HAVE_STACK_OVERFLOW_HANDLING && !WINDOWSNT */ static void deliver_arith_signal (int sig) @@ -2147,7 +2165,17 @@ snprintf (char *buf, size_t bufsize, char const *format, ...) /* If a backtrace is available, output the top lines of it to stderr. Do not output more than BACKTRACE_LIMIT or BACKTRACE_LIMIT_MAX lines. This function may be called from a signal handler, so it should - not invoke async-unsafe functions like malloc. */ + not invoke async-unsafe functions like malloc. + + If BACKTRACE_LIMIT is -1, initialize tables that 'backtrace' uses + but do not output anything. This avoids some problems that can + otherwise occur if the malloc arena is corrupted before 'backtrace' + is called, since 'backtrace' may call malloc if the tables are not + initialized. + + If the static variable THREAD_BACKTRACE_NPOINTERS is nonzero, a + fatal error has occurred in some other thread; generate a thread + backtrace instead, ignoring BACKTRACE_LIMIT. */ void emacs_backtrace (int backtrace_limit) { @@ -2164,6 +2192,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); } @@ -2683,10 +2719,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. */ @@ -2701,7 +2735,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. */ @@ -2723,7 +2756,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) @@ -2736,7 +2768,6 @@ list_system_processes (void) return proclist; } - GCPRO1 (proclist); len /= sizeof (struct kinfo_proc); for (i = 0; i < len; i++) { @@ -2746,7 +2777,6 @@ list_system_processes (void) proclist = Fcons (make_fixnum_or_float (procs[i].ki_pid), proclist); #endif } - UNGCPRO; xfree (procs); @@ -2957,7 +2987,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); @@ -2965,8 +2994,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); @@ -3155,7 +3182,6 @@ system_process_attributes (Lisp_Object pid) attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs); } - UNGCPRO; return attrs; } @@ -3194,7 +3220,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); @@ -3203,8 +3228,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); @@ -3297,7 +3320,6 @@ system_process_attributes (Lisp_Object pid) attrs = Fcons (Fcons (Qargs, decoded_cmd), attrs); } unbind_to (count, Qnil); - UNGCPRO; return attrs; } @@ -3333,7 +3355,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; @@ -3344,8 +3365,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 (); @@ -3483,7 +3502,6 @@ system_process_attributes (Lisp_Object pid) attrs = Fcons (Fcons (Qargs, decoded_comm), attrs); } - UNGCPRO; return attrs; }