From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id E51FD385800D for ; Sat, 11 Sep 2021 12:02:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E51FD385800D Received: from imap1.suse-dmz.suse.de (imap1.suse-dmz.suse.de [192.168.254.73]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 13CAD1FEDD for ; Sat, 11 Sep 2021 12:02:06 +0000 (UTC) Received: from imap1.suse-dmz.suse.de (imap1.suse-dmz.suse.de [192.168.254.73]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap1.suse-dmz.suse.de (Postfix) with ESMTPS id ED3C91332A for ; Sat, 11 Sep 2021 12:02:05 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap1.suse-dmz.suse.de with ESMTPSA id HoBVOL2aPGHCQQAAGKfGzw (envelope-from ) for ; Sat, 11 Sep 2021 12:02:05 +0000 Date: Sat, 11 Sep 2021 14:02:04 +0200 From: Tom de Vries To: gdb-patches@sourceware.org Subject: [PATCH][gdb] Make execute_command_to_string return string on throw Message-ID: <20210911120202.GA16898@delia.home> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 11 Sep 2021 12:02:08 -0000 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(-) 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 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. */ @@ -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 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. */ @@ -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