[RFC master/7.12.1] Don't propagate C++ exceptions across readline using SjLj on SjLj-based exception unwinding
Pedro Alves
palves@redhat.com
Tue Dec 20 11:50:00 GMT 2016
On 12/19/2016 02:42 PM, Yao Qi wrote:
> Nowadays, we propagate C++ exceptions across readline using
> setjmp/longjmp 89525768cd086a0798a504c81fdf7ebcd4c904e1
> (Propagate GDB/C++ exceptions across readline using sj/lj-based TRY/CATCH)
> because DWARF-based unwinding can't cross C function (see
> details from the commit above). However, SjLj-based exception
> unwinding doesn't have such issue.
Nice find.
I built a sjlj-based GCC trunk here, and building GDB with that
indeed triggers this.
>
> What is more, looks longjmp may break the SjLj-based exception
> handling, because _Unwind_SjLj_Unregister, which is put the exit
> of function, is not executed due to longjmp.
>
> (gdb) [New Thread 2936.0xb80]
> kill
>
> Thread 1 received signal SIGSEGV, Segmentation fault.
> 0x03ff662b in ?? ()
> top?bt 15
> #0 0x03ff662b in ?? ()
> #1 0x00526b92 in stdin_event_handler (error=0, client_data=0x172ed8)
> at ../../binutils-gdb/gdb/event-top.c:555
> #2 0x00525a94 in handle_file_event (ready_mask=<optimized out>,
> file_ptr=0x3ff5cb8) at ../../binutils-gdb/gdb/event-loop.c:733
...
>
> I dig into libcc/unwind-sjlj.c and gcc/except.c, but I still
> don't find much clue. This patch fixes this issue by not propagating
> the exception via setjmp/longjmp if __USING_SJLJ_EXCEPTIONS__.
I think I have a working approach that isn't specific to sjlj
exceptions, which I'd prefer. I.e., use "noexcept", to make
the compiler understand that the function doesn't throw, and hence
doesn't need to issue _Unwind_SjLj_Register / _Unwind_SjLj_Unregister
calls. That seems to do the trick. I tried both -O0 and -O2 (with
GCC trunk). Does this work for you too?
>From fd8544c25b0f383fcc9517687a38c538d91e53c1 Mon Sep 17 00:00:00 2001
From: Pedro Alves <palves@redhat.com>
Date: Tue, 20 Dec 2016 11:26:36 +0000
Subject: [PATCH] noexcept
---
gdb/event-top.c | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/gdb/event-top.c b/gdb/event-top.c
index acf8474..fa58def 100644
--- a/gdb/event-top.c
+++ b/gdb/event-top.c
@@ -157,10 +157,12 @@ void (*after_char_processing_hook) (void);
sjlj-based TRY/CATCH mechanism, which knows to handle multiple
levels of active setjmp/longjmp frames, needed in order to handle
the readline callback recursing, as happens with e.g., secondary
- prompts / queries, through gdb_readline_wrapper. */
+ prompts / queries, through gdb_readline_wrapper. This must be
+ noexcept in order to avoid problems with mixing sjlj and
+ (sjlj-based) C++ exceptions. */
-static void
-gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
+static struct gdb_exception
+gdb_rl_callback_read_char_wrapper_noexcept () noexcept
{
struct gdb_exception gdb_expt = exception_none;
@@ -180,6 +182,15 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
}
END_CATCH_SJLJ
+ return gdb_expt;
+}
+
+static void
+gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
+{
+ struct gdb_exception gdb_expt
+ = gdb_rl_callback_read_char_wrapper_noexcept ();
+
/* Rethrow using the normal EH mechanism. */
if (gdb_expt.reason < 0)
throw_exception (gdb_expt);
@@ -187,10 +198,12 @@ gdb_rl_callback_read_char_wrapper (gdb_client_data client_data)
/* GDB's readline callback handler. Calls the current INPUT_HANDLER,
and propagates GDB exceptions/errors thrown from INPUT_HANDLER back
- across readline. See gdb_rl_callback_read_char_wrapper. */
+ across readline. See gdb_rl_callback_read_char_wrapper. This must
+ be noexcept in order to avoid problems with mixing sjlj and
+ (sjlj-based) C++ exceptions. */
static void
-gdb_rl_callback_handler (char *rl)
+gdb_rl_callback_handler (char *rl) noexcept
{
struct gdb_exception gdb_rl_expt = exception_none;
struct ui *ui = current_ui;
--
2.5.5
More information about the Gdb-patches
mailing list