There's code in annotate.c and breakpoint.c that is supposed to
authorPedro Alves <palves@redhat.com>
Tue, 22 Jan 2013 20:08:30 +0000 (20:08 +0000)
committerPedro Alves <palves@redhat.com>
Tue, 22 Jan 2013 20:08:30 +0000 (20:08 +0000)
commit187d10dd19b822ba6e5470f1bd67fc94f5b48a86
tree90106f7725e75696d3848868d809d39d8ce02fd9
parentd84cf7eb3ef329f79b6484070dcb2a24e64e6be6
There's code in annotate.c and breakpoint.c that is supposed to
suppress multiple breakpoints-invalid annotations when the ignore
count of a breakpoint changes, up until the target actually stops.

But, the code is bogus:

void
annotate_breakpoints_changed (void)
{
  if (annotation_level == 2)
    {
      target_terminal_ours ();
      printf_unfiltered (("\n\032\032breakpoints-invalid\n"));
      if (ignore_count_changed)
ignore_count_changed = 0;   /* Avoid multiple break annotations.  */
    }
}

The "ignore_count_changed" flag isn't actually guarding the output of
the annotation at all.  It would have been better written something
like:

void
annotate_breakpoints_changed (void)
{
  if (annotation_level == 2 && !ignore_count_changed)
    {
      target_terminal_ours ();
      printf_unfiltered (("\n\032\032breakpoints-invalid\n"));
      ignore_count_changed = 0;   /* Avoid multiple break annotations.  */
    }
}

but, it wasn't.  AFAICS, that goes all the way back to the original
patch'es submission and check in, at
<http://sourceware.org/ml/gdb-patches/1999-q4/msg00106.html>.  I
looked a tar of HP's wdb from 1999, and even though that contains
local changes in the annotate code, this suppression seems borked
there too to me.

The original patch added a test to supposedly exercise this
suppression, but, it actually doesn't.  It merely tests that
"breakpoints-invalid" is output after "stopped", but doesn't check
whether the duplicates supression actually works (IOW, check that only
_one_ annotation is seen).  I was going to simply delete the tests
too, but a following patch will eliminate the duplicates in a
different way (which I needed for a different reason), so instead, I'm
making the tests actually fail if a duplicate annotation is seen.

Worry not, the test doesn't actually fail!  The reason is that
breakpoint.c does:

      else if (b->ignore_count > 0)
{
  b->ignore_count--;
  annotate_ignore_count_change ();
  bs->stop = 0;
  /* Increase the hit count even though we don't stop.  */
  ++(b->hit_count);
  observer_notify_breakpoint_modified (b);
}

where the annotate_ignore_count_change call is meant to inform the
"breakpoint_modified" annotation observer to ignore the notification.
All sounds good.  But, the trouble is that nowadays annotate.c only
installs the observers if GDB is started with annotations enabled with
a command line option (gdb --annotate=2):

void
_initialize_annotate (void)
{
  if (annotation_level == 2)
    {
      observer_attach_breakpoint_deleted (breakpoint_changed);
      observer_attach_breakpoint_modified (breakpoint_changed);
    }
}

and annota1.exp, to enable annotations, starts GDB normally, and
afterwards does "set annotate 2", so the observers aren't installed
when annota1.exp is run, and therefore changing the ignore count isn't
triggering any annotation at all...

gdb/
2013-01-22  Pedro Alves  <palves@redhat.com>

* annotate.c (ignore_count_changed): Delete.
(annotate_breakpoints_changed): Don't clear ignore_count_changed.
(annotate_ignore_count_change): Delete.
(annotate_stopped): Don't emit a delayed breakpoints-changed
annotation.
* annotate.h (annotate_ignore_count_change): Delete.
* breakpoint.c (bpstat_check_breakpoint_conditions): Don't call
annotate_ignore_count_change.

gdb/testsuite/
2013-01-22  Pedro Alves  <palves@redhat.com>

* gdb.base/annota1.exp (annotate ignore count change): Add
expected output for failure case.
gdb/ChangeLog
gdb/annotate.c
gdb/annotate.h
gdb/breakpoint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/annota1.exp