@@ -1539,7 +1539,16 @@
ofunc = signal (SIGSEGV, gdb_demangle_signal_handler);
#endif
- crash_signal = SIGSETJMP (gdb_demangle_jmp_buf);
+ /* The signal handler may keep the signal blocked when we longjmp out
+ of it. If we have sigprocmask, we can use it to unblock the signal
+ afterwards and we can avoid the performance overhead of saving the
+ signal mask just in case the signal gets triggered. Otherwise, just
+ tell sigsetjmp to save the mask. */
+#ifdef HAVE_SIGPROCMASK
+ crash_signal = SIGSETJMP (gdb_demangle_jmp_buf, 0);
+#else
+ crash_signal = SIGSETJMP (gdb_demangle_jmp_buf, 1);
+#endif
}
#endif
@@ -1559,6 +1568,14 @@
{
static int error_reported = 0;
+#ifdef HAVE_SIGPROCMASK
+ /* If we got the signal, SIGSEGV may still be blocked; restore it. */
+ sigset_t segv_sig_set;
+ sigemptyset (&segv_sig_set);
+ sigaddset (&segv_sig_set, SIGSEGV);
+ sigprocmask (SIG_UNBLOCK, &segv_sig_set, NULL);
+#endif
+
if (!error_reported)
{
std::string short_msg
@@ -23,11 +23,13 @@
#ifdef HAVE_SIGSETJMP
#define SIGJMP_BUF sigjmp_buf
-#define SIGSETJMP(buf) sigsetjmp((buf), 1)
+#define SIGSETJMP(buf,val) sigsetjmp((buf), val)
#define SIGLONGJMP(buf,val) siglongjmp((buf), (val))
#else
#define SIGJMP_BUF jmp_buf
-#define SIGSETJMP(buf) setjmp(buf)
+/* We ignore val here because that's safer and avoids having to check
+ whether _setjmp exists. */
+#define SIGSETJMP(buf,val) setjmp(buf)
#define SIGLONGJMP(buf,val) longjmp((buf), (val))
#endif