From 551cb6a52d99c04055afed182479a8780a15f4a1 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Wed, 29 Oct 2014 11:58:12 +0000 Subject: [PATCH] TUI: don't let exceptions escape while handling readline key bindings I noticed that with: $ TERM=dumb ./gdb -q -nx Cannot enable the TUI: terminal doesn't support cursor addressing [TERM=dumb] (gdb) The next key the user types is silently eaten. The problem is that we're throwing an exception while in a readline callback that isn't prepared for that: (top-gdb) bt #0 tui_enable () at /home/pedro/gdb/mygit/build/../src/gdb/tui/tui.c:388 #1 0x000000000051f47b in tui_rl_switch_mode (notused1=1, notused2=1) at /home/pedro/gdb/mygit/build/../src/gdb/tui/tui.c:101 #2 0x0000000000768d6f in _rl_dispatch_subseq (key=1, map=0xd069c0 , got_subseq=0) at /home/pedro/gdb/mygit/build/../src/readline/readline.c:774 #3 0x0000000000768acb in _rl_dispatch_callback (cxt=0x1ce6190) at /home/pedro/gdb/mygit/build/../src/readline/readline.c:686 #4 0x000000000078120b in rl_callback_read_char () at /home/pedro/gdb/mygit/build/../src/readline/callback.c:170 #5 0x0000000000619445 in rl_callback_read_char_wrapper (client_data=0x0) at /home/pedro/gdb/mygit/build/../src/gdb/event-top.c:166 #6 0x000000000061981b in stdin_event_handler (error=0, client_data=0x0) at /home/pedro/gdb/mygit/build/../src/gdb/event-top.c:372 #7 0x000000000061840e in handle_file_event (data=...) at /home/pedro/gdb/mygit/build/../src/gdb/event-loop.c:762 #8 0x00000000006178f5 in process_event () at /home/pedro/gdb/mygit/build/../src/gdb/event-loop.c:339 #9 0x00000000006179bc in gdb_do_one_event () at /home/pedro/gdb/mygit/build/../src/gdb/event-loop.c:403 #10 0x0000000000617a0c in start_event_loop () at /home/pedro/gdb/mygit/build/../src/gdb/event-loop.c:428 Here, in _rl_dispatch_subseq: 769 770 rl_executing_keymap = map; 771 772 rl_dispatching = 1; 773 RL_SETSTATE(RL_STATE_DISPATCHING); 774 (*map[key].function)(rl_numeric_arg * rl_arg_sign, key); 775 RL_UNSETSTATE(RL_STATE_DISPATCHING); 776 rl_dispatching = 0; 777 778 /* If we have input pending, then the last command was a prefix 779 command. Don't change the state of rl_last_func. Otherwise, GDB is called from line 774, but longjmp'ing at that point leaves rl_dispatching and RL_STATE_DISPATCHING set. Fix this by wrapping tui_rl_switch_mode in a TRY_CATCH. gdb/ 2014-10-29 Pedro Alves * tui/tui.c (tui_rl_switch_mode): Wrap tui_enable/tui_disable in TRY_CATCH. --- gdb/ChangeLog | 5 +++++ gdb/tui/tui.c | 27 +++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 67679310672..88c18e07af3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2014-10-29 Pedro Alves + + * tui/tui.c (tui_rl_switch_mode): Wrap tui_enable/tui_disable in + TRY_CATCH. + 2014-10-29 Joel Brobecker * arm-tdep.c (arm_skip_stack_protector): Return early if diff --git a/gdb/tui/tui.c b/gdb/tui/tui.c index ca66ccd0f4f..cb85fb02200 100644 --- a/gdb/tui/tui.c +++ b/gdb/tui/tui.c @@ -90,15 +90,30 @@ static Keymap tui_readline_standard_keymap; static int tui_rl_switch_mode (int notused1, int notused2) { - if (tui_active) + volatile struct gdb_exception ex; + + /* Don't let exceptions escape. We're in the middle of a readline + callback that isn't prepared for that. */ + TRY_CATCH (ex, RETURN_MASK_ALL) { - tui_disable (); - rl_prep_terminal (0); + if (tui_active) + { + tui_disable (); + rl_prep_terminal (0); + } + else + { + /* If tui_enable throws, we'll re-prep below. */ + rl_deprep_terminal (); + tui_enable (); + } } - else + if (ex.reason < 0) { - rl_deprep_terminal (); - tui_enable (); + exception_print (gdb_stderr, ex); + + if (!tui_active) + rl_prep_terminal (0); } /* Clear the readline in case switching occurred in middle of -- 2.30.2