Subject: Re: bug#79403: 30.1; M-x gdb startup problem with (eq gdb-debuginfod-enable-setting 'ask)

From: Eli Zaretskii <[email-masked]>
Date: Sat, 13 Sep 2025 17:07:28 +0300

> From: Gustav Hållberg <[email-masked]>
> Date: Sat, 13 Sep 2025 12:25:52 +0200
> Cc: [email-masked]
> 
>  Thanks.  Does the patch below give good results?
> 
> Yes but gud-filter-defer-flag seems to be a global so if you have several gdb sessions going they all get
> confused while waiting for the y-or-no-p.
> 
> To test I did:
> 1. M-x gdb, start debugging process A, stop at breakpoint
> 2. M-x gdb, attach to process B, waiting at y-or-n-p
> 3. Type "step" in A's gdb window
> 4. Answer "y" to the y-or-n-p for B
> 
> This sent output from A's gdb to B's gdb buffer!
> 
> It seems gud-filter-defer-flag and gud-filter-pending-text should be buffer-local (or process properties?) to
> avoid this.
> But I don't know this code at all so...
> 
> That said, your patch is definitely a big improvement and the above error case is a bit contrived :)

Thanks, how about the patch below?

diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index 74dff32..ebaff4a2 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1108,7 +1108,9 @@ gdb-init-1
   ;; trigger questions about debuginfod queries.
   (if (eq gdb-debuginfod-enable 'ask)
       (setq gdb-debuginfod-enable
-            (y-or-n-p "Enable querying debuginfod servers for this session?")))
+            (let ((gud-filter-defer-flag t))
+              (y-or-n-p
+               "Enable querying debuginfod servers for this session?"))))
   (gdb-input (format "-gdb-set debuginfod enabled %s"
                      (if gdb-debuginfod-enable "on" "off"))
              'gdb-debuginfod-message)
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 5980bc2..1d43028 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -793,6 +793,10 @@ gdb-first-prompt
 (defvar gud-filter-pending-text nil
   "Non-nil means this is text that has been saved for later in `gud-filter'.")
 
+(defvar gud-filter-defer-flag nil
+  "Non-nil means don't process anything from the debugger right now.
+It is saved for when this flag is not set.")
+
 ;; One of the nice features of GDB is its impressive support for
 ;; context-sensitive command completion.  We preserve that feature
 ;; in the GUD buffer by using a GDB command designed just for Emacs.
@@ -2829,6 +2833,11 @@ gud-common-init
   (if find-file (setq-local gud-find-file find-file))
   (setq gud-last-last-frame nil)
 
+  ;; We need these to be local to the process's buffer so that we could
+  ;; defer processing output for each debugging session separately.
+  (make-local-variable 'gud-filter-defer-flag)
+  (make-local-variable 'gud-filter-pending-text)
+
   (set-process-filter (get-buffer-process (current-buffer)) #'gud-filter)
   (set-process-sentinel (get-buffer-process (current-buffer)) #'gud-sentinel)
   (gud-set-buffer))
@@ -2837,34 +2846,32 @@ gud-set-buffer
   (when (derived-mode-p 'gud-mode)
     (setq gud-comint-buffer (current-buffer))))
 
-(defvar gud-filter-defer-flag nil
-  "Non-nil means don't process anything from the debugger right now.
-It is saved for when this flag is not set.")
-
 ;; These functions are responsible for inserting output from your debugger
 ;; into the buffer.  The hard work is done by the method that is
 ;; the value of gud-marker-filter.
 
 (defun gud-filter (proc string)
   ;; Here's where the actual buffer insertion is done
-  (let (output process-window)
-    (if (buffer-name (process-buffer proc))
-	(if gud-filter-defer-flag
-	    ;; If we can't process any text now,
-	    ;; save it for later.
-	    (setq gud-filter-pending-text
-		  (concat (or gud-filter-pending-text "") string))
-
-	  ;; If we have to ask a question during the processing,
-	  ;; defer any additional text that comes from the debugger
-	  ;; during that time.
-	  (let ((gud-filter-defer-flag t))
-	    ;; Process now any text we previously saved up.
-	    (if gud-filter-pending-text
-		(setq string (concat gud-filter-pending-text string)
-		      gud-filter-pending-text nil))
+  (let ((proc-buf (process-buffer proc))
+        (cbuf (current-buffer))
+        output process-window)
+    (if (buffer-name proc-buf)
+        (with-current-buffer proc-buf
+	  (if gud-filter-defer-flag
+	      ;; If we can't process any text now,
+	      ;; save it for later.
+	      (setq gud-filter-pending-text
+		    (concat (or gud-filter-pending-text "") string))
+
+	    ;; If we have to ask a question during the processing,
+	    ;; defer any additional text that comes from the debugger
+	    ;; during that time.
+	    (let ((gud-filter-defer-flag t))
+	      ;; Process now any text we previously saved up.
+	      (if gud-filter-pending-text
+		  (setq string (concat gud-filter-pending-text string)
+		        gud-filter-pending-text nil))
 
-	    (with-current-buffer (process-buffer proc)
 	      ;; If we have been so requested, delete the debugger prompt.
 	      (save-restriction
 		(widen)
@@ -2887,23 +2894,22 @@ gud-filter
 
 	      ;; Let the comint filter do the actual insertion.
 	      ;; That lets us inherit various comint features.
-	      (comint-output-filter proc output))
-
-	    ;; Put the arrow on the source line.
-	    ;; This must be outside of the save-excursion
-	    ;; in case the source file is our current buffer.
-	    (if process-window
-		(with-selected-window process-window
-		  (gud-display-frame))
-	      ;; We have to be in the proper buffer, (process-buffer proc),
-	      ;; but not in a save-excursion, because that would restore point.
-	      (with-current-buffer (process-buffer proc)
-		(gud-display-frame))))
-
-	  ;; If we deferred text that arrived during this processing,
-	  ;; handle it now.
-	  (if gud-filter-pending-text
-	      (gud-filter proc ""))))))
+	      (comint-output-filter proc output)
+
+	      ;; Put the arrow on the source line.
+	      ;; This must be outside of the save-excursion
+	      ;; in case the source file is our current buffer.
+	      (if process-window
+		  (with-selected-window process-window
+		    (gud-display-frame))
+	        ;; We are in the proper buffer, (process-buffer proc),
+	        ;; but not in a save-excursion, because that would restore point.
+		(gud-display-frame)))
+
+	    ;; If we deferred text that arrived during this processing,
+	    ;; handle it now.
+	    (if gud-filter-pending-text
+	        (gud-filter proc "")))))))
 
 (defvar gud-minor-mode-type nil)
 (defvar gud-overlay-arrow-position nil)