Make execute_command_to_string return string on throw

Message ID 20210911120202.GA16898@delia.home
State New
Headers show
Series
  • Make execute_command_to_string return string on throw
Related show

Commit Message

Lancelot SIX via Gdb-patches Sept. 11, 2021, 12:02 p.m.
Hi,

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.

Any comments?

Thanks,
- Tom

[gdb] Make execute_command_to_string return string on throw

---
 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           | 34 +++++++++++++++++++++++++++-------
 7 files changed, 47 insertions(+), 20 deletions(-)

Patch

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 27550c1faee..05ffd7fd0ee 100644
--- a/gdb/gdbcmd.h
+++ b/gdb/gdbcmd.h
@@ -145,7 +145,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.  */
 
@@ -154,8 +155,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 5918bb414a3..34c1be76a16 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -1888,11 +1888,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 ();
 
@@ -1901,7 +1901,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 516e4d45696..edfda3a4e55 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -3026,8 +3026,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 10c3dcd6991..019c658bc47 100644
--- a/gdb/thread.c
+++ b/gdb/thread.c
@@ -1457,8 +1457,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 7e95ed3969c..ff240eed657 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -728,13 +728,22 @@  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.  */
@@ -748,12 +757,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