From patchwork Sat Feb 3 02:15:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Aaron Merey X-Patchwork-Id: 85257 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2F3523857C4C for ; Sat, 3 Feb 2024 02:16:26 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id BFA6A3858403 for ; Sat, 3 Feb 2024 02:15:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org BFA6A3858403 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org BFA6A3858403 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706926559; cv=none; b=KOqDJgv+5f9c6v6r2CGFpPcle1UghxFDAHrlOj4tpBg5qSVYSdaM0K4S79QNR6LifkgxeLfhJ24hyNytE11dVprU3t1ase+24zU2fUsbAjadJZAb6hGRlYwH0w5zL8CKo8tsdH7ypJGq3cpyBKaS0CrknSkSJBHOiRpydTS8lTQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706926559; c=relaxed/simple; bh=z5Vc8gLxAWwRVp4y0C1tGx9q5DZ1V+ossKbbUey0MXg=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=xE6VqdWXFCx+rlXjWN2IH0T5brnljjkQDnuK38sUHlCZx3Ot9TI4Juk/rzbRUh12mRwjR9yysVv+jCf2kz0AbvRZb8qlKxGT+CNUc/QeCiWJ1eDA8IKHzuwL2+cY/nHHlcmlHQFomx6C2DsLO8ORp8Feic/2yu1EbMCPr0+cGug= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1706926556; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qSvbJnq0nS+bB6DyXxfTjgOxZdNFl8tQRj3m6tmhoN0=; b=RMH/i3FhcE0OQx8mxTjjFumz7+0U82gRL6qAhaUte/uxMi+T3l+ySES6ipvsIu7ebiUbmS qHpREXqBkfk2CvtKY8uazOwhQmBA65CtG/6ITv01p3pS8x19aZxCr0HjyUYbGWPaA8eql/ wm8zUMc+L7BHde+BkjOo6Z1FhQkMUes= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-441-13ZkFrszPJmf0aNrhLFghA-1; Fri, 02 Feb 2024 21:15:53 -0500 X-MC-Unique: 13ZkFrszPJmf0aNrhLFghA-1 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2975585A589; Sat, 3 Feb 2024 02:15:53 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.22.32.56]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6A9091C060AF; Sat, 3 Feb 2024 02:15:52 +0000 (UTC) From: Aaron Merey To: gdb-patches@sourceware.org Cc: Aaron Merey , =?utf-8?q?Martin_Li=C5=A1ka?= , Tom de Vries Subject: [PATCH v4] gdb/debuginfod: Ctrl-C asks to cancel further downloads Date: Fri, 2 Feb 2024 21:15:15 -0500 Message-ID: <20240203021515.705567-1-amerey@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-12.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org v3: https://sourceware.org/pipermail/gdb-patches/2023-March/197679.html v4 includes changes needed to apply the patch to the current master branch. Currently gdb only allows for debuginfod downloads to be cancelled one at a time via Ctrl-C. This can be a burden if one wishes to cancel a large series of downloads. Additionally there can also be ambiguity between whether Ctrl-C during a download was intended to cancel a download or interrupt the inferior. This patch addresses these issues by adding a new debuginfod setting and changing the behavior of Ctrl-C during a download. Add a new command "set debuginfod cancel one/all/ask", where: - "one" means Ctrl-C cancels one download, - "all" means Ctrl-C cancels all further downloads, and - "ask" means Ctrl-C asks whether to cancel all further downloads. A "yes" implies "set debuginfod cancel all", and a "no" implies "set debuginfod cancel one", so the question is only asked once. Note that the behaviour as it was before this patch is equivalent to "set debuginfod cancel one". Instead, the new default is "set debuginfod cancel ask". Note that cancelling all further downloads implies "set debuginfod enabled off". A single Ctrl-C during downloading now sets the quit_flag and proceeds with all downloads. If the inferior has the terminal, then a second Ctrl-C during downloading triggers a query asking whether to cancel the download or interrupt the inferior. If the user wishes to cancel the download then the setting of 'set debuginfod cancel' determines whether one or all downloads are cancelled. In the case of "set debuginfod cancel ask", there will be another query at this point asking whether to cancel one or all downloads. If the inferior does not have the terminal, then a second Ctrl-C during downloading simply cancels the download according to the setting of "set debuginfod cancel". In this case there is no query asking whether to interrupt the inferior or cancel a download. Example session where inferior has terminal: (gdb) run [...] Downloading separate debug info for /lib64/libxyz.so [### ]^C^C Cancel the current download? If no, then Ctrl-C will be sent to the target process. ([y] or n) y Cancelling download of separate debug info for /lib64/libxyz.so... Cancel further downloading for this session? (y or [n]) n Downloading separate debug info for /lib64/libabcd.so Example session where inferior does not have terminal: (gdb) run [...] Downloading separate debug info for /lib64/libxyz.so [### ]^C^C Cancelling download of separate debug info for /lib64/libxyz.so... Cancel further downloading for this session? (y or [n]) y Debuginfod has been disabled. To re-enable use the 'set debuginfod enabled' command. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29582 Suggested-By: Martin Liška Co-Authored-By: Tom de Vries Reviewed-By: Eli Zaretskii --- gdb/debuginfod-support.c | 183 +++++++++++++++++++++++++++++++++++++-- gdb/doc/gdb.texinfo | 21 +++++ 2 files changed, 199 insertions(+), 5 deletions(-) diff --git a/gdb/debuginfod-support.c b/gdb/debuginfod-support.c index 7d8ada39e96..97d4b2f2bac 100644 --- a/gdb/debuginfod-support.c +++ b/gdb/debuginfod-support.c @@ -38,6 +38,8 @@ static cmd_list_element *maint_show_debuginfod_cmdlist; static const char debuginfod_on[] = "on"; static const char debuginfod_off[] = "off"; static const char debuginfod_ask[] = "ask"; +static const char debuginfod_one[] = "one"; +static const char debuginfod_all[] = "all"; static const char *debuginfod_enabled_enum[] = { @@ -47,6 +49,20 @@ static const char *debuginfod_enabled_enum[] = nullptr }; +/* Valid values for set debuginfod cancel command. */ + +static const char *debuginfod_cancel_enum[] = +{ + debuginfod_one, + debuginfod_all, + debuginfod_ask, + nullptr +}; + +/* Value of debuginfod cancellation mode. */ + +static const char *debuginfod_cancel = debuginfod_ask; + static const char *debuginfod_enabled = #if defined(HAVE_LIBDEBUGINFOD) debuginfod_ask; @@ -109,9 +125,11 @@ debuginfod_section_query (const unsigned char *build_id, struct user_data { user_data (const char *desc, const char *fname) - : desc (desc), fname (fname) + : pass_quit_flag (false), inf_had_term (false), desc (desc), fname (fname) { } + bool pass_quit_flag; + bool inf_had_term; const char * const desc; const char * const fname; ui_out::progress_update progress; @@ -156,10 +174,83 @@ progressfn (debuginfod_client *c, long cur, long total) if (check_quit_flag ()) { ui_file *outstream = get_unbuffered (gdb_stdout); - gdb_printf (outstream, _("Cancelling download of %s %s...\n"), - data->desc, styled_fname.c_str ()); - return 1; - } + + /* If a single Ctrl-C occurs during downloading, let it propagate to the + target. If more than one Ctrl-C occurs, ask whether to cancel the + current download or interrupt the target. If the download is + cancelled, the setting of debuginfod_cancel will determine whether + the current download is cancelled or debuginfod is disabled. */ + if (!data->pass_quit_flag) + data->pass_quit_flag = true; + else + { + int resp = 1; + bool extra_nl = false; + + if (data->inf_had_term) + { + /* If Ctrl-C occurs during the following prompts, catch the + exception to prevent unsafe early returns to gdb's main + event loop. During these prompts, Ctrl-C is equivalent to + answering 'y'. */ + try + { + resp = yquery (_("Cancel the current download?\nIf no, " + "then Ctrl-C will be sent to the target " + "process. ")); + } + catch (const gdb_exception &) + { + /* If the query doesn't complete, then we need an additional + newline to get "Cancelling download of..." printed on a + separate line. */ + extra_nl = true; + } + } + if (resp) + { + if (extra_nl) + { + gdb_printf (outstream, "\n"); + extra_nl = false; + } + + gdb_printf (outstream, _("Cancelling download of %s %s...\n"), + data->desc, styled_fname.c_str ()); + if (debuginfod_cancel == debuginfod_ask) + { + try + { + resp = nquery + (_("Cancel further downloading for this session? ")); + } + catch (const gdb_exception &) + { + resp = 1; + extra_nl = true; + } + + if (resp) + debuginfod_cancel = debuginfod_all; + else + debuginfod_cancel = debuginfod_one; + } + if (debuginfod_cancel == debuginfod_all) + { + if (extra_nl) + gdb_printf (outstream, "\n"); + + gdb_printf (outstream, + _("Debuginfod has been disabled.\nTo re-enable " + "use the 'set debuginfod enabled' command.\n")); + debuginfod_enabled = debuginfod_off; + } + + data->pass_quit_flag = false; + return 1; + } + } + } if (debuginfod_verbose == 0) return 0; @@ -330,6 +421,10 @@ debuginfod_source_query (const unsigned char *build_id, user_data data ("source file", srcpath); debuginfod_set_user_data (c, &data); + + if (!target_terminal::is_ours ()) + data.inf_had_term = true; + if (target_supports_terminal_ours ()) { term_state.emplace (); @@ -341,6 +436,11 @@ debuginfod_source_query (const unsigned char *build_id, build_id_len, srcpath, &dname)); + if (data.pass_quit_flag) + set_quit_flag (); + if (data.inf_had_term && term_state.has_value ()) + target_terminal::inferior (); + debuginfod_set_user_data (c, nullptr); } @@ -376,6 +476,10 @@ debuginfod_debuginfo_query (const unsigned char *build_id, user_data data ("separate debug info for", filename); debuginfod_set_user_data (c, &data); + + if (!target_terminal::is_ours ()) + data.inf_had_term = true; + if (target_supports_terminal_ours ()) { term_state.emplace (); @@ -384,6 +488,12 @@ debuginfod_debuginfo_query (const unsigned char *build_id, fd = scoped_fd (debuginfod_find_debuginfo (c, build_id, build_id_len, &dname)); + + if (data.pass_quit_flag) + set_quit_flag (); + if (data.inf_had_term && term_state.has_value ()) + target_terminal::inferior (); + debuginfod_set_user_data (c, nullptr); } @@ -419,6 +529,10 @@ debuginfod_exec_query (const unsigned char *build_id, user_data data ("executable for", filename); debuginfod_set_user_data (c, &data); + + if (!target_terminal::is_ours ()) + data.inf_had_term = true; + if (target_supports_terminal_ours ()) { term_state.emplace (); @@ -427,6 +541,11 @@ debuginfod_exec_query (const unsigned char *build_id, fd = scoped_fd (debuginfod_find_executable (c, build_id, build_id_len, &dname)); + if (data.pass_quit_flag) + set_quit_flag (); + if (data.inf_had_term && term_state.has_value ()) + target_terminal::inferior (); + debuginfod_set_user_data (c, nullptr); } @@ -467,6 +586,10 @@ debuginfod_section_query (const unsigned char *build_id, { user_data data (desc.c_str (), filename); debuginfod_set_user_data (c, &data); + + if (!target_terminal::is_ours ()) + data.inf_had_term = true; + if (target_supports_terminal_ours ()) { term_state.emplace (); @@ -475,6 +598,12 @@ debuginfod_section_query (const unsigned char *build_id, fd = scoped_fd (debuginfod_find_section (c, build_id, build_id_len, section_name, &dname)); + + if (data.pass_quit_flag) + set_quit_flag (); + if (data.inf_had_term && term_state.has_value ()) + target_terminal::inferior (); + debuginfod_set_user_data (c, nullptr); } @@ -523,6 +652,33 @@ show_debuginfod_enabled (ui_file *file, int from_tty, cmd_list_element *cmd, "\"%s\".\n"), debuginfod_enabled); } +/* Set callback for "set debuginfod cancel". */ + +static void +set_debuginfod_cancel (const char *value) +{ + debuginfod_cancel = value; +} + +/* Get callback for "set debuginfod cancel". */ + +static const char * +get_debuginfod_cancel () +{ + return debuginfod_cancel; +} + +/* Show callback for "set debuginfod cancel". */ + +static void +show_debuginfod_cancel (ui_file *file, int from_tty, cmd_list_element *cmd, + const char *value) +{ + gdb_printf (file, + _("Debuginfod cancellation mode is currently set to " + "\"%s\".\n"), debuginfod_cancel); +} + /* Set callback for "set debuginfod urls". */ static void @@ -627,6 +783,23 @@ When set to \"ask\", prompt whether to enable or disable debuginfod." ), &set_debuginfod_prefix_list, &show_debuginfod_prefix_list); + add_setshow_enum_cmd ("cancel", class_run, debuginfod_cancel_enum, + _("Set Ctrl-C behaviour for debuginfod."), + _("Show Ctrl-C behaviour for debuginfod."), + _("\ +When set to \'one\', pressing Ctrl-C twice cancels a single \ +download.\nWhen set to \'all\', pressing Ctrl-C twice cancels all further downloads.\n\ +When set to \'ask\', pressing Ctrl-C twice asks what to do.\nA single Ctrl-C during \ +downloading is passed to the target process being debugged.\nA second Ctrl-C \ +during downloading may raise a prompt asking whether to cancel the download or \ +send Ctrl-C to the target.\nIf the download is cancelled, then no Ctrl-C is \ +sent to the target."), + set_debuginfod_cancel, + get_debuginfod_cancel, + show_debuginfod_cancel, + &set_debuginfod_prefix_list, + &show_debuginfod_prefix_list); + /* set/show debuginfod urls */ add_setshow_string_noescape_cmd ("urls", class_run, _("\ Set the list of debuginfod server URLs."), _("\ diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index e98c15242bc..d6df28896b1 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -50259,6 +50259,27 @@ is set to @code{ask} for interactive sessions. Display whether @code{debuginfod enabled} is set to @code{on}, @code{off} or @code{ask}. +@kindex set debuginfod cancel +@anchor{set debuginfod cancel} +@item set debuginfod cancel +@itemx set debuginfod cancel one +@cindex debuginfod @kbd{Ctrl-C} behaviour +Pressing @kbd{Ctrl-C} twice during downloading will cancel the current +download. + +@item set debuginfod cancel all +Pressing @kbd{Ctrl-C} twice during downloading will cancel this and all +further downloads. + +@item set debuginfod cancel ask +Pressing @kbd{Ctrl-C} twice during downloading will cancel the current +download and prompt whether to cancel all further downloads. By default, +@code{debuginfod cancel} is set to @code{ask} for interactive sessions. + +@kindex show debuginfod cancel +@item show debuginfod cancel +Display the current setting of @code{debuginfod cancel}. + @kindex set debuginfod urls @cindex configure debuginfod URLs @item set debuginfod urls