diff --git a/gdb/infrun.c b/gdb/infrun.c index 428359c5580..6550ee40e1c 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -4429,17 +4429,7 @@ wait_for_inferior (inferior *inf) finish_state.release (); } -/* 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 () { struct ui *ui = current_ui; diff --git a/gdb/infrun.h b/gdb/infrun.h index 1227472ebc4..0a7cdadf1fa 100644 --- a/gdb/infrun.h +++ b/gdb/infrun.h @@ -418,5 +418,14 @@ private: bool m_prev_enable_commit_resumed; }; +/* Cleanup that reinstalls the readline callback handler, if the + target is running in the background. If 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 when going 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. */ +extern void reinstall_readline_callback_handler_cleanup (); #endif /* GDB_INFRUN_H */ diff --git a/gdb/run-on-main-thread.c b/gdb/run-on-main-thread.c index 6410eb53036..131317bcbb6 100644 --- a/gdb/run-on-main-thread.c +++ b/gdb/run-on-main-thread.c @@ -21,6 +21,8 @@ #include "gdbsupport/cleanups.h" #include "gdbsupport/cxx-thread.h" #include "gdbsupport/event-loop.h" +#include "infrun.h" +#include "gdbsupport/scope-exit.h" /* The serial event used when posting runnables. */ @@ -60,6 +62,10 @@ run_events (int error, gdb_client_data client_data) local = std::move (runnables); } + /* Schedule cleanup in case secondary prompts (for instance, the pagination + prompt) happened while running events. */ + SCOPE_EXIT { reinstall_readline_callback_handler_cleanup (); }; + for (auto &item : local) { try diff --git a/gdb/testsuite/gdb.python/py-post-event.exp b/gdb/testsuite/gdb.python/py-post-event.exp new file mode 100644 index 00000000000..e37a7cf2fc6 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-post-event.exp @@ -0,0 +1,36 @@ +# Copyright 2026 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Regression test for PR24796. Check that a pagination prompt while handling +# a posted event doesn't crash GDB. + +foreach_with_prefix pagination { off on } { + clean_restart + + gdb_test_no_output "set pagination $pagination" + gdb_test_no_output "set height 8" + + gdb_test -no-prompt-anchor "source py-post-event.py" + if { $pagination == "on" } { + gdb_test_multiple "" "" { + -re $pagination_prompt { + send_gdb "c\n" + } + } + } + + # Check that prompt is reactive. + gdb_test "print 1" " = 1" +} diff --git a/gdb/testsuite/gdb.python/py-post-event.py b/gdb/testsuite/gdb.python/py-post-event.py new file mode 100644 index 00000000000..efd8f3396f9 --- /dev/null +++ b/gdb/testsuite/gdb.python/py-post-event.py @@ -0,0 +1,24 @@ +# Copyright 2026 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import gdb + + +def Event(): + for x in range(0, 10): + print("Line") + + +gdb.post_event(Event)