[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