[gdb] Make execute_command_to_string return string on throw
authorTom de Vries <tdevries@suse.de>
Sat, 9 Oct 2021 16:58:30 +0000 (18:58 +0200)
committerTom de Vries <tdevries@suse.de>
Sat, 9 Oct 2021 16:58:30 +0000 (18:58 +0200)
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
gdb/gdbcmd.h
gdb/guile/guile.c
gdb/python/python.c
gdb/stack.c
gdb/thread.c
gdb/top.c

index 525a3a7eacf4bd1cb020863664f573cdbf4b9d0c..a823fcb0020676718de6cfbe46aecef138878e74 100644 (file)
@@ -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)
index 59afb0aa2ede87ae1667be9f6dfd2dc692aff26e..39f5ede3eaf5b17cf861c4a3993ddd60c7708968 100644 (file)
@@ -42,7 +42,8 @@ extern void execute_fn_to_ui_file (struct ui_file *file, std::function<void(void
    (e.g. with styling).  When TERM_OUT is false raw output will be collected
    (e.g. no styling).  */
 
-extern std::string execute_fn_to_string (std::function<void(void)> fn, bool term_out);
+extern void execute_fn_to_string (std::string &res,
+                                 std::function<void(void)> 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 *);
index a28dee37ed875cb9ad839094a22e6dede42b5b88..8ba840cba6a86e29524bb41b7ef1558aff794c15 100644 (file)
@@ -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);
 
index 451c5bdfe0b6d5ebddcd8c4176e3f9e4f316a393..264f7c88ed66c4f4f4bdb19d425e238fcbd07d67 100644 (file)
@@ -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)
     {
index 8b29ab505e5c0dd86cadde28c1245918b12a5ec3..bedadb0f491399e70cf4d3246be3687d132d760e 100644 (file)
@@ -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."));
index ebe2d7833e3321f2a0ce6b32bc2b508a8a6b7466..9abb51179d6b9f48a5c5fb5c78edd4f4a8e03b26 100644 (file)
@@ -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)
index 08cdb487df482f82a4d0bd7db2eb149af0ee92e4..1f9e649a85d6043cd5ade885e48e9e09dc7fd6e5 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -724,13 +724,25 @@ execute_fn_to_ui_file (struct ui_file *file, std::function<void(void)> fn)
 
 /* See gdbcmd.h.  */
 
-std::string
-execute_fn_to_string (std::function<void(void)> fn, bool term_out)
+void
+execute_fn_to_string (std::string &res, std::function<void(void)> 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);
 }
 \f
 /* When nonzero, cause dont_repeat to do nothing.  This should only be