Subject: bug#64186: Patch: Suppress deprecated '-gdb-set target-async' warning message in gdb-mi.el

From: Wang Diancheng <[email-masked]>
Date: Fri, 30 Jun 2023 15:08:18 +0800

Eli Zaretskii <[email-masked]> 于2023年6月29日周四 14:08写道：
>
> > From: Wang Diancheng <[email-masked]>
> > Date: Wed, 28 Jun 2023 11:51:39 +0800
> > Cc: [email-masked], [email-masked]
> >
> > I did some hacks to make gdb-non-stop work, patch is attached. The
> > patch try to set `gdb-non-stop` when target is running or at first
> > stop. Sorry for rough patch. I'm new for elisp.
>
> Thanks.  This looks about right to me, except that "run&" is not the
> only command whose side effect is that the debuggee is running in the
> background mode.  We also need to at least consider "attach&", I
> think.  Maybe it would be useful to have a list of such commands, so
> that we could expand it as needed in the future, because currently I
> don't really understand what triggers background execution that causes
> "-list-target-features" to report "async".  It sounds possible that
> this happens only after the first command that ends with "&", in which
> case we will need to add to the list all the commands mentioned in the
> "Background Execution" node of the GDB manual.  This affects the test
> below:
>

Thanks for your comments.I think what exactly the value of
`gdb-last-command’ is not essential for us.
We just need to know  whether `gdb-last-command' is a CLI command in
the background or a MI command,
since here we have already got its "running" status.  We must check
the target "async" feature after stopping
the debuggee at the first time in function `gdb-stopped' if
`gdb-last-command' is not a background CLI command or a MI command.

> > +  ;; Set `gdb-non-stop` when `gdb-last-command` is a CLI background
> > +  ;; `run` command e.g. r& or MI command `-exec-run`
> > +  (when (or (string-match "&\s*$" gdb-last-command)
> > +            (string-match "-exec-run" gdb-last-command))
> > +    (gdb-try-check-target-async-support))
>
> And I'm not sure I understand the idea behind this part:
>
> > @@ -2722,6 +2744,9 @@ gdb-stopped
> >
> >      ;; Print "(gdb)" to GUD console
> >      (when gdb-first-done-or-error
> > +      ;; If run target with CLI foreground command `run`, `target
> > +      ;; async` can only be checked when target is stopped
> > +      (gdb-try-check-target-async-support)
> >        (setq gdb-filter-output (concat gdb-filter-output gdb-prompt-name)))
>
> Can you elaborate?

Thanks for your questions, according to my comments above, If the
debuggee has been started by
a non-background CLI command e.g. “run" or "attach" (no trailing "&")
commands, we can only
check the target "async" feature at the code stack.

>
> Finally, please don't quote symbols `like this` in comments.  Our
> conventions are to quote symbols 'like this' or `like this'.

I updated the patch, see the attachment.
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index c9afe502a50..199be3318a1 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -237,6 +237,7 @@ gdb-handler-list
 (defvar gdb-source-file-list nil
   "List of source files for the current executable.")
 (defvar gdb-first-done-or-error t)
+(defvar gdb-target-async-checked nil)
 (defvar gdb-source-window-list nil
   "List of windows used for displaying source files.
 Sorted in most-recently-visited-first order.")
@@ -453,9 +454,7 @@ gdb-debug-log-max
           (const   :tag "Unlimited" nil))
   :version "22.1")
 
-;; This is disabled by default because we don't really support
-;; asynchronous execution of the debuggee; see bug#63084.  FIXME.
-(defcustom gdb-non-stop-setting nil
+(defcustom gdb-non-stop-setting (not (eq system-type 'windows-nt))
   "If non-nil, GDB sessions are expected to support the non-stop mode.
 When in the non-stop mode, stopped threads can be examined while
 other threads continue to execute.
@@ -470,7 +469,7 @@ gdb-non-stop-setting
 GDB session needs to be restarted for this setting to take effect."
   :type 'boolean
   :group 'gdb-non-stop
-  :version "29.1")
+  :version "30.1")
 
 (defcustom gdb-debuginfod-enable-setting
   ;; debuginfod servers are only for ELF executables, and elfutils, of
@@ -1069,6 +1068,7 @@ gdb-init-1
 	gdb-handler-list '()
 	gdb-prompt-name nil
 	gdb-first-done-or-error t
+	gdb-target-async-checked nil
 	gdb-buffer-fringe-width (car (window-fringes))
 	gdb-debug-log nil
 	gdb-source-window-list nil
@@ -1078,7 +1078,8 @@ gdb-init-1
         gdb-threads-list '()
         gdb-breakpoints-list '()
         gdb-register-names '()
-        gdb-non-stop gdb-non-stop-setting
+        gdb-supports-non-stop nil
+        gdb-non-stop nil
         gdb-debuginfod-enable gdb-debuginfod-enable-setting)
   ;;
   (gdbmi-bnf-init)
@@ -1110,7 +1111,7 @@ gdb-init-1
     (gdb-input "-gdb-set interactive-mode on" 'ignore))
   (gdb-input "-gdb-set height 0" 'ignore)
 
-  (when gdb-non-stop
+  (when gdb-non-stop-setting
     (gdb-input "-gdb-set non-stop 1" 'gdb-non-stop-handler))
 
   (gdb-input "-enable-pretty-printing" 'ignore)
@@ -1145,16 +1146,30 @@ gdb-non-stop-handler
 	(setq gdb-non-stop nil)
 	(setq gdb-supports-non-stop nil))
     (setq gdb-supports-non-stop t)
-    (gdb-input "-gdb-set target-async 1" 'ignore)
+    ;; Try to use "mi-async" first, needs GDB 7.7 onwards.  Note if
+    ;; "mi-async" is not available, GDB is still running in "sync"
+    ;; mode, "No symbol" for "mi-async" must appear before other
+    ;; commands.
+    (gdb-input "-gdb-set mi-async 1" 'gdb-set-mi-async-handler)))
+
+(defun gdb-set-mi-async-handler()
+  (goto-char (point-min))
+  (if (re-search-forward "No symbol" nil t)
+      (gdb-input "-gdb-set target-async 1" 'ignore)))
+
+(defun gdb-try-check-target-async-support()
+  (when (and gdb-non-stop-setting gdb-supports-non-stop
+             (not gdb-target-async-checked))
     (gdb-input "-list-target-features" 'gdb-check-target-async)))
 
 (defun gdb-check-target-async ()
   (goto-char (point-min))
-  (unless (re-search-forward "async" nil t)
+  (if (re-search-forward "async" nil t)
+      (setq gdb-non-stop t)
     (message
      "Target doesn't support non-stop mode.  Turning it off.")
-    (setq gdb-non-stop nil)
-    (gdb-input "-gdb-set non-stop 0" 'ignore)))
+    (gdb-input "-gdb-set non-stop 0" 'ignore))
+  (setq gdb-target-async-checked t))
 
 (defun gdb-delchar-or-quit (arg)
   "Delete ARG characters or send a quit command to GDB.
@@ -2652,6 +2667,14 @@ gdb-running
 (defun gdb-starting (_output-field _result)
   ;; CLI commands don't emit ^running at the moment so use gdb-running too.
   (setq gdb-inferior-status "running")
+
+  ;; Set `gdb-non-stop' when `gdb-last-command' is a CLI background
+  ;; running command e.g. "run &", attach &" or a MI command
+  ;; e.g. "-exec-run" or "-exec-attach".
+  (when (or (string-match "&\s*$" gdb-last-command)
+            (string-match "^-" gdb-last-command))
+    (gdb-try-check-target-async-support))
+
   (gdb-force-mode-line-update
    (propertize gdb-inferior-status 'face font-lock-type-face))
   (setq gdb-active-process t)
@@ -2722,6 +2745,10 @@ gdb-stopped
 
     ;; Print "(gdb)" to GUD console
     (when gdb-first-done-or-error
+      ;; If running target with a non-background CLI command
+      ;; e.g. "run" (no trailing '&'), target async feature can only
+      ;; be checked when when the program stops for the first time
+      (gdb-try-check-target-async-support)
       (setq gdb-filter-output (concat gdb-filter-output gdb-prompt-name)))
 
     ;; In non-stop, we update information as soon as another thread gets