aboutsummaryrefslogtreecommitdiff
path: root/gdb/cp-support.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/cp-support.c')
-rw-r--r--gdb/cp-support.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index cd732b6..253369b 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -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