Subject: 24.3.50; gud commands stop responding when using gdb-mi
From: Jean-Philippe Gravel <[email-masked]>
To: [email-masked]
Date: Thu, 28 Feb 2013 21:02:56 -0500
List-Id: <debbugs-submit.debbugs.gnu.org>

When debugging a program using gdb-mi, the gud commands (gud-break for
instance) stop responding.  I get the problem all the time on the
trunk version of Emacs (revision 111899).  I have gdb version 7.5.1
installed.  The following steps should reproduce the problem:

Start Emacs:
  cd trunk/src
  ./emacs -Q

Start a another Emacs in gdb-mi.  Use the CLI interface to start the program:
  M-x gdb
  Run gdb (like this): gdb -i=mi emacs
  (gdb) run

Back in the first emacs, break GDB:
  C-c C-c

Open one of the Emacs source file (emacs.c)
  C-x C-f
  Find file: ../trunk/src/emacs.c

In the function main, position the cursor on a line of code and try to
set a break point using the gud command:
  M-x gud-break

The break point is successfully created.  Return to the *gud-emacs*
buffer and resume the debugged Emacs, then break again:
  (gdb) continue
  C-c C-c

Go back in the emacs.c file and try to set a breakpoint again in the
main function.  From this point on, the gud-break will refuse to work.
 The internal state of gdb-mi is in fact in a stall.  Several other
features of gdb-mi are also disabled.  For instance, if you start
gdb-many-windows:
  M-x gdb-many-windows

and click on the Threads tab, the buffer will be empty even though the
debugged program isn't running.

I investigated the problem and found it's root in the gdb-mi.el file.
When typing "run" in the debugger, GDB responds with a "^running"
message.  gdb-mi handles this by calling the gdb-starting function.
In this function, you will find the following:
  (defun gdb-starting (_output-field)
    [...]
    ;; GDB doesn't seem to respond to -thread-info before first stop or
    ;; thread exit (even in non-stop mode), so this is useless.
    ;; Behavior may change in the future.
    (gdb-emit-signal gdb-buf-publisher 'update-threads))

Indeed, GDB doesn't respond to the -thread-info command.
Nevertheless, gdb-mi records the -thread-info request in the variable
gdb-pending-trigger and will refuse to send any other -thread-info
command until GDB responds the command gdb-mi is waiting for.

Back to our stalled gdb-mi, if we probe the gdb-pending-trigger
variable, we get:
  C-h v
  Describe variable: gdb-pending-trigger
    gdb-pending-triggers is a variable defined in `gdb-mi.el'.
    Its value is ((#<buffer *threads of emacs*> . gdb-invalidate-threads))

We can get back on our feet by clearing that variable:
  M-:
  Eval: (setq gdb-pending-triggers nil)

and then run a CLI command in GDB:
  (gdb) where

Only resetting the variable is not enough on it's own, but running a
CLI command right after seems to wake-up gdb-mi out of it's coma.
After this, you can run gud commands again and gdb-many-windows is
back to life.

Commenting out the (gdb-emit-signal gdb-buf-publisher 'update-threads)
statement in both gdb-starting and gdb-running helps quite a bit, but
this fix is not enough.  I sometimes encounter cases where gdb-mi
fails to receive replies for a bunch of other commands to update all
other gdb window (breakpoints, call-stack, etc.)  Unfortunately, this
condition is harder to encounter and I cannot provide repro-steps at
this point.

I do not know if this should be considered an emacs or a GDB bug
(should GDB always reply to commands, even when the program is
running?)  What I can say for sure is that there is definitively room
for improvement on the emacs side: the pending message handling should
be more robust and gdb-mi should not hang if GDB skips a reply.

In GNU Emacs 24.3.50.1 (i686-pc-linux-gnu, GTK+ Version 3.4.2)
 of 2013-02-28 on ubuntu
Bzr revision: 111899 [email-masked]
Windowing system distributor `The X.Org Foundation', version 11.0.11103000
System Description:	Ubuntu 12.04.1 LTS

Important settings:
  value of $LANG: en_US.UTF-8
  locale-coding-system: utf-8-unix
  default enable-multibyte-characters: t

Major mode: C/l

Minor modes in effect:
  gdb-many-windows: t
  tooltip-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  line-number-mode: t
  transient-mark-mode: t
  abbrev-mode: t

Recent input:
M-x g d b <return> <C-backspace> <C-backspace> e m
a c s <return> r u n <return> C-c C-c C-x C-f e m a
c s . c <return> C-s m a i n SPC ( C-s <down> <down>
<down> C-x SPC C-x b <return> c o n t i n u e <return>
C-c C-c C-x b <return> <down> <down> C-x SPC C-x b
<return> M-x g d b - m a n y - w i n d o w <return>
<help-echo> <help-echo> <down-mouse-1> <mouse-1> <help-echo>
<help-echo> <help-echo> C-h v g d b - p e n d i n g
<tab> <return> q M-: ( s e t q SPC g d b - p e n d
i n <tab> t r <tab> SPC n i l ) <return> w h e r e
<return> <help-echo> <help-echo> <help-echo> <help-echo>
<help-echo> <down-mouse-1> <mouse-1> C-x SPC <help-echo>
M-x r e p o r t - e m a c s - b u g <return>

Recent messages:
For information about GNU Emacs and the GNU system, type C-h C-a.
Switched to thread 1
Loading cc-langs...done
Mark saved where search started
Command: break emacs.c:654
Gdb-Many-Windows mode enabled
Type "q" to restore previous buffer.
nil
Command: break emacs.c:656

Load-path shadows:
None found.

Features:
(shadow sort gnus-util mail-extr emacsbug message cl-macs gv format-spec
rfc822 mml mml-sec mm-decode mm-bodies mm-encode mail-parse rfc2231
mailabbrev gmm-utils mailheader sendmail rfc2047 rfc2045 ietf-drums
mm-util mail-prsvr mail-utils pp help-mode help-fns cus-start cus-load
misearch multi-isearch vc-bzr cc-langs cl nadvice cl-lib cc-mode
cc-fonts easymenu cc-guess cc-menus cc-cmds cc-styles cc-align cc-engine
cc-vars cc-defs gdb-mi bindat json gud easy-mmode comint ansi-color ring
time-date tooltip ediff-hook vc-hooks lisp-float-type mwheel x-win x-dnd
tool-bar dnd fontset image regexp-opt fringe tabulated-list newcomment
lisp-mode register page menu-bar rfn-eshadow timer select scroll-bar
mouse jit-lock font-lock syntax facemenu font-core frame cham georgian
utf-8-lang misc-lang vietnamese tibetan thai tai-viet lao korean
japanese hebrew greek romanian slovak czech european ethiopic indian
cyrillic chinese case-table epa-hook jka-cmpr-hook help simple abbrev
minibuffer loaddefs button faces cus-face macroexp files text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget
hashtable-print-readable backquote make-network-process inotify
dynamic-setting system-font-setting font-render-setting move-toolbar gtk
x-toolkit x multi-tty emacs)