From 84a6adfd4c7bc9e99a270b8a111da7218a0e89a5 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Sat, 9 Oct 2021 18:58:30 +0200 Subject: [PATCH] [gdb] Make execute_command_to_string return string on throw The pattern for using execute_command_to_string is: ... std::string output; output = execute_fn_to_string (fn, term_out); ... This results in a problem when using it in a try/catch: ... try { output = execute_fn_to_string (fn, term_out) } catch (const gdb_exception &e) { /* Use output. */ } ... If an expection was thrown during execute_fn_to_string, then the output remains unassigned, while it could be worthwhile to known what output was generated by gdb before the expection was thrown. Fix this by returning the string using a parameter instead: ... execute_fn_to_string (output, fn, term_out) ... Also add a variant without string parameter, to support places where the function is used while ignoring the result: ... execute_fn_to_string (fn, term_out) ... Tested on x86_64-linux. --- gdb/complaints.c | 4 ++-- gdb/gdbcmd.h | 12 +++++++++--- gdb/guile/guile.c | 2 +- gdb/python/python.c | 6 +++--- gdb/stack.c | 4 ++-- gdb/thread.c | 5 +++-- gdb/top.c | 37 ++++++++++++++++++++++++++++++------- 7 files changed, 50 insertions(+), 20 deletions(-) diff --git a/gdb/complaints.c b/gdb/complaints.c index 525a3a7eacf..a823fcb0020 100644 --- a/gdb/complaints.c +++ b/gdb/complaints.c @@ -91,7 +91,7 @@ test_complaints () do \ { \ std::string output; \ - output = execute_fn_to_string ([]() { complaint (STR); }, false); \ + execute_fn_to_string (output, []() { complaint (STR); }, false); \ std::string expected \ = _("During symbol reading: ") + std::string (STR "\n"); \ SELF_CHECK (output == expected); \ @@ -102,7 +102,7 @@ test_complaints () do \ { \ std::string output; \ - output = execute_fn_to_string ([]() { complaint (STR); }, false); \ + execute_fn_to_string (output, []() { complaint (STR); }, false); \ SELF_CHECK (output.empty ()); \ SELF_CHECK (counters[STR] == CNT); \ } while (0) diff --git a/gdb/gdbcmd.h b/gdb/gdbcmd.h index 59afb0aa2ed..39f5ede3eaf 100644 --- a/gdb/gdbcmd.h +++ b/gdb/gdbcmd.h @@ -42,7 +42,8 @@ extern void execute_fn_to_ui_file (struct ui_file *file, std::function fn, bool term_out); +extern void execute_fn_to_string (std::string &res, + std::function fn, bool term_out); /* As execute_fn_to_ui_file, but run execute_command for P and FROM_TTY. */ @@ -51,8 +52,13 @@ extern void execute_command_to_ui_file (struct ui_file *file, /* As execute_fn_to_string, but run execute_command for P and FROM_TTY. */ -extern std::string execute_command_to_string (const char *p, int from_tty, - bool term_out); +extern void execute_command_to_string (std::string &res, const char *p, + int from_tty, bool term_out); + +/* As execute_command_to_string, but ignore resulting string. */ + +extern void execute_command_to_string (const char *p, + int from_tty, bool term_out); extern void print_command_line (struct command_line *, unsigned int, struct ui_file *); diff --git a/gdb/guile/guile.c b/gdb/guile/guile.c index a28dee37ed8..8ba840cba6a 100644 --- a/gdb/guile/guile.c +++ b/gdb/guile/guile.c @@ -302,7 +302,7 @@ gdbscm_execute_gdb_command (SCM command_scm, SCM rest) scoped_restore preventer = prevent_dont_repeat (); if (to_string) - to_string_res = execute_command_to_string (command, from_tty, false); + execute_command_to_string (to_string_res, command, from_tty, false); else execute_command (command, from_tty); diff --git a/gdb/python/python.c b/gdb/python/python.c index 451c5bdfe0b..264f7c88ed6 100644 --- a/gdb/python/python.c +++ b/gdb/python/python.c @@ -1924,11 +1924,11 @@ namespace selftests { static void test_python () { -#define CMD execute_command_to_string ("python print(5)", 0, true); +#define CMD(S) execute_command_to_string (S, "python print(5)", 0, true) std::string output; - output = CMD; + CMD (output); SELF_CHECK (output == "5\n"); output.clear (); @@ -1937,7 +1937,7 @@ test_python () = make_scoped_restore (&gdb_python_initialized, 0); try { - output = CMD; + CMD (output); } catch (const gdb_exception &e) { diff --git a/gdb/stack.c b/gdb/stack.c index 8b29ab505e5..bedadb0f491 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -3028,8 +3028,8 @@ frame_apply_command_count (const char *which_command, set to the selected frame. */ scoped_restore_current_thread restore_fi_current_frame; - cmd_result = execute_command_to_string - (cmd, from_tty, gdb_stdout->term_out ()); + execute_command_to_string + (cmd_result, cmd, from_tty, gdb_stdout->term_out ()); } fi = get_selected_frame (_("frame apply " "unable to get selected frame.")); diff --git a/gdb/thread.c b/gdb/thread.c index ebe2d7833e3..9abb51179d6 100644 --- a/gdb/thread.c +++ b/gdb/thread.c @@ -1450,8 +1450,9 @@ thr_try_catch_cmd (thread_info *thr, const char *cmd, int from_tty, try { - std::string cmd_result = execute_command_to_string - (cmd, from_tty, gdb_stdout->term_out ()); + std::string cmd_result; + execute_command_to_string + (cmd_result, cmd, from_tty, gdb_stdout->term_out ()); if (!flags.silent || cmd_result.length () > 0) { if (!flags.quiet) diff --git a/gdb/top.c b/gdb/top.c index 08cdb487df4..1f9e649a85d 100644 --- a/gdb/top.c +++ b/gdb/top.c @@ -724,13 +724,25 @@ execute_fn_to_ui_file (struct ui_file *file, std::function fn) /* See gdbcmd.h. */ -std::string -execute_fn_to_string (std::function fn, bool term_out) +void +execute_fn_to_string (std::string &res, std::function fn, + bool term_out) { string_file str_file (term_out); - execute_fn_to_ui_file (&str_file, fn); - return std::move (str_file.string ()); + try + { + execute_fn_to_ui_file (&str_file, fn); + } + catch (...) + { + /* Finally. */ + res = std::move (str_file.string ()); + throw; + } + + /* And finally. */ + res = std::move (str_file.string ()); } /* See gdbcmd.h. */ @@ -744,12 +756,23 @@ execute_command_to_ui_file (struct ui_file *file, /* See gdbcmd.h. */ -std::string +void +execute_command_to_string (std::string &res, const char *p, int from_tty, + bool term_out) +{ + execute_fn_to_string (res, [=]() { execute_command (p, from_tty); }, + term_out); +} + +/* See gdbcmd.h. */ + +void execute_command_to_string (const char *p, int from_tty, bool term_out) { - return - execute_fn_to_string ([=]() { execute_command (p, from_tty); }, term_out); + std::string dummy; + execute_fn_to_string (dummy, [=]() { execute_command (p, from_tty); }, + term_out); } /* When nonzero, cause dont_repeat to do nothing. This should only be -- 2.30.2