Allow not saving the signal state in SIGSETJMP
authorChristian Biesinger <cbiesinger@google.com>
Tue, 15 Oct 2019 15:02:33 +0000 (10:02 -0500)
committerChristian Biesinger <cbiesinger@google.com>
Wed, 16 Oct 2019 21:13:43 +0000 (16:13 -0500)
Saving the signal state is very slow (this patch is a 14% speedup).  The
reason we need this code is because signal handler will leave the
signal blocked when we longjmp out of it.  But in this case we can
just manually unblock the signal instead of taking the unconditional
perf hit.

gdb/ChangeLog:

2019-10-16  Christian Biesinger  <cbiesinger@google.com>

* gdbsupport/gdb_setjmp.h (SIGSETJMP): Allow passing in the value to
pass on to sigsetjmp's second argument.
* cp-support.c (gdb_demangle): Unblock SIGSEGV if we caught a crash.

Change-Id: Ib3010966050c64b4cc8b47d8cb45871652b0b3ea

gdb/ChangeLog
gdb/cp-support.c
gdb/gdbsupport/gdb_setjmp.h

index d11dbfbfcfd391f8d9fa63359df625e53ed94146..ba028ed230f68eefa56cd2fe5b21888e505b8fb3 100644 (file)
@@ -1,3 +1,9 @@
+2019-10-16  Christian Biesinger  <cbiesinger@google.com>
+
+       * gdbsupport/gdb_setjmp.h (SIGSETJMP): Allow passing in the value to
+       pass on to sigsetjmp's second argument.
+       * cp-support.c (gdb_demangle): Unblock SIGSEGV if we caught a crash.
+
 2019-10-16  Keith Seitz  <keiths@redhat.com>
 
        PR gdb/23567
index cd732b60e7d9c6a7d89588dada4666756d161794..253369b1efe5ea37c615e0af9ba158bfd48c3329 100644 (file)
@@ -1539,7 +1539,16 @@ gdb_demangle (const char *name, int options)
       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 @@ gdb_demangle (const char *name, int options)
        {
          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
index d4ebbfa8f2a2a45dbc6c9e1ed91b2788525a1fdd..499597085b8f33b54e392fccab56e18270d806c2 100644 (file)
 
 #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