[gdb] Handle pagination prompt during posted event
PR python/24796 reports the following problem.
We have a python file test.py:
...
import gdb
def Event():
for x in range(0, 10):
print("Line")
gdb.post_event(Event)
...
Without pagination, we simple have:
...
(gdb) source test.py
(gdb) Line
Line
...
Line
Line
print 1
$1 = 1
(gdb)
...
But with pagination (and height set to 8), we get instead:
...
(gdb) source test.py
(gdb) Line
Line
...
Line
--Type <RET> for more, q to quit, c to continue without paging--c
Line
Line
Line
print 1
readline: readline_callback_read_char() called with no handler!
Fatal signal: Aborted
----- Backtrace -----
0x651099 gdb_internal_backtrace_1
/data/vries/gdb/src/gdb/bt-utils.c:122
0x651137 _Z22gdb_internal_backtracev
/data/vries/gdb/src/gdb/bt-utils.c:175
0x9462aa handle_fatal_signal
/data/vries/gdb/src/gdb/event-top.c:1008
0x7f4efaf5f08f ???
/usr/src/debug/glibc-2.40/signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
0x7f4efafb245c __pthread_kill_implementation
/usr/src/debug/glibc-2.40/nptl/pthread_kill.c:44
0x7f4efaf5efc5 __GI_raise
../sysdeps/posix/raise.c:26
0x7f4efaf46916 __GI_abort
/usr/src/debug/glibc-2.40/stdlib/abort.c:79
0x117502b rl_callback_read_char
/data/vries/gdb/src/readline/readline/callback.c:139
0x944bc2 gdb_rl_callback_read_char_wrapper_sjlj
/data/vries/gdb/src/gdb/event-top.c:197
0x944cd3 gdb_rl_callback_read_char_wrapper_noexcept
/data/vries/gdb/src/gdb/event-top.c:240
0x944d51 gdb_rl_callback_read_char_wrapper
/data/vries/gdb/src/gdb/event-top.c:252
0x10623e3 stdin_event_handler
/data/vries/gdb/src/gdb/ui.c:154
0x1a06e9c handle_file_event
/data/vries/gdb/src/gdbsupport/event-loop.cc:551
0x1a074df gdb_wait_for_event
/data/vries/gdb/src/gdbsupport/event-loop.cc:672
0x1a063bc _Z16gdb_do_one_eventi
/data/vries/gdb/src/gdbsupport/event-loop.cc:263
0x6d547f _ZN6interp12do_one_eventEi
/data/vries/gdb/src/gdb/interps.h:93
0xb77fb6 start_event_loop
/data/vries/gdb/src/gdb/main.c:403
0xb781a4 captured_command_loop
/data/vries/gdb/src/gdb/main.c:468
0xb7a10d captured_main
/data/vries/gdb/src/gdb/main.c:1381
0xb7a209 _Z8gdb_mainP18captured_main_args
/data/vries/gdb/src/gdb/main.c:1400
0x419704 main
/data/vries/gdb/src/gdb/gdb.c:38
...
What leads to the crash, is that this code in gdb_readline_wrapper_line:
...
/* Prevent parts of the prompt from being redisplayed if annotations
are enabled, and readline's state getting out of sync. We'll
reinstall the callback handler, which puts the terminal in raw
mode (or in readline lingo, in prepped state), when we're next
ready to process user input, either in display_gdb_prompt, or if
we're handling an asynchronous target event and running in the
background, just before returning to the event loop to process
further input (or more target events). */
if (current_ui->command_editing)
gdb_rl_callback_handler_remove ();
...
when activated by the pagination prompt removes the callback handler (which
sets rl_linefunc to NULL).
The comment mentions re-installing the callback handler, but that doesn't
happen, so when calling rl_callback_read_char we run into:
...
if (rl_linefunc == NULL)
{
_rl_errmsg ("readline_callback_read_char() called with no handler!");
abort ();
}
...
An example of re-installation is found here in infrun.c:
...
/* Cleanup that reinstalls the readline callback handler, if the
target is running in the background. If while handling the target
event something triggered a secondary prompt, like e.g., a
pagination prompt, we'll have removed the callback handler (see
gdb_readline_wrapper_line). Need to do this as we go back to the
event loop, ready to process further input. Note this has no
effect if the handler hasn't actually been removed, because calling
rl_callback_handler_install resets the line buffer, thus losing
input. */
static void
void
reinstall_readline_callback_handler_cleanup ()
...
Fix the crash by adding the same cleanup in run_events.
Tested on x86_64-linux.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24796
5 files changed