public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom de Vries <tdevries@suse.de>
To: gdb-patches@sourceware.org
Subject: [PATCH v5 5/6] [gdb/cli] Ask if source highlighting should be interrupted
Date: Tue, 24 Oct 2023 11:49:32 +0200	[thread overview]
Message-ID: <20231024094933.12009-6-tdevries@suse.de> (raw)
In-Reply-To: <20231024094933.12009-1-tdevries@suse.de>

When source highlighting is done using the GNU source-highlight library,
and it takes a long time, it can be interrupted using ^C, but that cancels the
rest of the command:
...
$ gdb -q a.out -ex "b 56"
Reading symbols from a.out...
Breakpoint 1 at 0x400e2a: file test.cpp, line 56.
(gdb) r
Starting program: /data/vries/gdb/a.out

Breakpoint 1, Solution::numOfSubarrays () at test.cpp:56
^C
(gdb)
...

That means in this case that the user doesn't get to see the line gdb stopped
at.

This is especially problematic if the user actually meant to interrupt the
inferior execution.

Instead, ask the user whether highlighting needs to be interrupted, and if so,
interrupt only the highlighting part, and continue with the command:
...
$ gdb -q a.out -ex "b 56"
Reading symbols from a.out...
Breakpoint 1 at 0x400e2a: file test.cpp, line 56.
(gdb) r
Starting program: /data/vries/gdb/a.out

Breakpoint 1, Solution::numOfSubarrays () at test.cpp:56
^CCancel source styling using GNU source highlight of \
  /data/vries/gdb/test.cpp?([y] or n) y
56	        return (int) t;
(gdb)
...

Note that after cancelling, line 56 still can be highlighted, just by pygments
instead of source-highlight.

Co-Authored-By: Lancelot Six <lancelot.six@amd.com>
Co-Authored-By: Pedro Alves <pedro@palves.net>

Tested on x86_64-linux.
---
 gdb/source-cache.c | 71 ++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 63 insertions(+), 8 deletions(-)

diff --git a/gdb/source-cache.c b/gdb/source-cache.c
index 2d59957f42c..6f514cbba3e 100644
--- a/gdb/source-cache.c
+++ b/gdb/source-cache.c
@@ -43,6 +43,7 @@
 #if GDB_SELF_TEST
 #include "gdbsupport/selftest.h"
 #include "event-top.h"
+#include "top.h"
 #endif
 
 /* The number of source files we'll cache.  */
@@ -200,10 +201,56 @@ get_language_name (enum language lang)
 class gdb_highlight_event_listener : public srchilite::HighlightEventListener
 {
 public:
+  explicit gdb_highlight_event_listener (const std::string &fullname)
+    : m_fullname (fullname)
+  {
+  }
+
   void notify (const srchilite::HighlightEvent &event) override
   {
-    QUIT;
+    /* If target_terminal::is_ours, we can ask the user a question and get an
+       answer.  We're not sure if or how !target_terminal::is_ours can happen.
+       Assert to catch it happening.  Note that we're asserting before
+       checking the quit flag, such that we don't rely on the user issuing
+       a SIGINT or SIGTERM to detect this.  */
+    gdb_assert (target_terminal::is_ours ());
+
+    if (!check_quit_flag ())
+      {
+	/* No SIGTERM or SIGINT pending, nothing to do.  */
+	return;
+      }
+
+    /* If we got a SIGTERM, skip querying.  This isn't strictly
+       necessary as yquery runs a nested event loop for the secondary
+       prompt, which runs pending async signal handlers.  However,
+       this helps with the unit test, which makes sure that the quit
+       call at the bottom throws a gdb_exception_forced_quit exception
+       and that our caller doesn't swallow it.  Note we may receive a
+       SIGTERM in between the query and the quit call.  */
+    if (!sync_quit_force_run)
+      {
+	/* Ask the user what to do.  */
+	int resp
+	  = (yquery
+	     (_("Cancel source styling using GNU source highlight of %s? "),
+	      m_fullname.c_str ()));
+	if (!resp)
+	  {
+	    /* Continue highlighting.  */
+	    return;
+	  }
+      }
+
+    /* Interrupt highlighting.  Note we don't abort via the QUIT macro
+       as that may do nothing.  E.g. if the current quit_handler is
+       infrun_quit_handler, and target_terminal::is_ours, pressing ^C
+       is ignored by QUIT.  */
+    quit ();
   }
+
+private:
+  const std::string &m_fullname;
 };
 
 #endif /* HAVE_SOURCE_HIGHLIGHT */
@@ -242,9 +289,6 @@ try_source_highlight (std::string &contents ATTRIBUTE_UNUSED,
 
 	  const std::string &datadir = srchilite::Settings::retrieveDataDir ();
 	  langmap = new srchilite::LangMap (datadir, "lang.map");
-
-	  static gdb_highlight_event_listener event_listener;
-	  highlighter->setHighlightEventListener (&event_listener);
 	}
 
       std::string detected_lang;
@@ -256,6 +300,12 @@ try_source_highlight (std::string &contents ATTRIBUTE_UNUSED,
 	  lang_name = detected_lang.c_str ();
 	}
 
+      gdb_highlight_event_listener event_listener (fullname);
+      highlighter->setHighlightEventListener (&event_listener);
+      /* Make sure that the highlighter's EventListener doesn't become a
+	 dangling pointer.  */
+      SCOPE_EXIT { highlighter->setHighlightEventListener (nullptr); };
+
       std::istringstream input (contents);
       std::ostringstream output;
       highlighter->highlight (input, output, lang_name, fullname);
@@ -269,8 +319,7 @@ try_source_highlight (std::string &contents ATTRIBUTE_UNUSED,
     }
   catch (const gdb_exception_quit &)
     {
-      /* SIGINT, rethrow.  */
-      throw;
+      /* SIGINT, ignore.  */
     }
   catch (...)
     {
@@ -356,6 +405,9 @@ static void gnu_source_highlight_test ()
     if (!a_signal_handler_selftest.valid ())
       return;
 
+    scoped_restore save_confirm
+      = make_scoped_restore (&confirm, false);
+
     /* Pretend user sent SIGINT by calling the signal handler.  */
     handle_sigint (SIGINT);
 
@@ -370,7 +422,7 @@ static void gnu_source_highlight_test ()
       {
 	saw_quit = true;
       }
-    SELF_CHECK (saw_quit);
+    SELF_CHECK (!saw_quit);
     SELF_CHECK (!res);
     SELF_CHECK (prog == styled_prog);
   }
@@ -439,13 +491,16 @@ source_cache::ensure (struct symtab *s)
 	     reasons:
 	     - the language is not supported.
 	     - the language cannot not be auto-detected from the file name.
+	     - styling took too long and was interrupted by the user.
 	     - no stylers available.
 
 	     Since styling failed, don't try styling the file again after it
 	     drops from the cache.
 
 	     Note that clearing the source cache also clears
-	     m_no_styling_files.  */
+	     m_no_styling_files, so if styling took too long, and the user
+	     interrupted it, and the source cache gets cleared, the user will
+	     need to interrupt styling again.  */
 	  m_no_styling_files.insert (fullname);
 	}
     }
-- 
2.35.3


  parent reply	other threads:[~2023-10-24  9:48 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-24  9:49 [PATCH v5 0/6] [gdb/cli] Allow source highlighting to " Tom de Vries
2023-10-24  9:49 ` [PATCH v5 1/6] [gdb/cli] Add signal_handler_selftest Tom de Vries
2023-11-22 16:26   ` Tom de Vries
2023-10-24  9:49 ` [PATCH v5 2/6] [gdb/python] Make python selftest more robust Tom de Vries
2023-10-24  9:49 ` [PATCH v5 3/6] [gdb/cli] Add gnu-source-highlight selftest Tom de Vries
2023-10-24 12:33   ` Tom de Vries
2023-10-24  9:49 ` [PATCH v5 4/6] [gdb/cli] Allow source highlighting to be interrupted Tom de Vries
2023-10-24  9:49 ` Tom de Vries [this message]
2023-10-24  9:49 ` [PATCH v5 6/6] [gdb/cli] Simplify gdb_highlight_event_listener::notify Tom de Vries

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231024094933.12009-6-tdevries@suse.de \
    --to=tdevries@suse.de \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).