Bug 29603 - Python Watchpoints are not deleted
Summary: Python Watchpoints are not deleted
Status: RESOLVED FIXED
Alias: None
Product: gdb
Classification: Unclassified
Component: python (show other bugs)
Version: HEAD
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-09-23 08:02 UTC by Johnson Sun
Modified: 2024-01-24 14:04 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments
Test C code (508 bytes, text/plain)
2022-09-23 08:04 UTC, Johnson Sun
Details
Test Python code (602 bytes, text/plain)
2022-09-23 08:04 UTC, Johnson Sun
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Johnson Sun 2022-09-23 08:02:52 UTC
In Python, if we register a local software watchpoint and set the `Breakpoint.stop' function to always return `False', the watchpoint will not be deleted when going out of scope.

This cause gdb to incorrectly trigger the `Breakpoint.stop' function many more times than it should.

This issue is reproduced in:
- GCC 7.5.0 & GDB 10.2 on Ubuntu 18.04,
- GCC 9.3.0 & GDB 9.2 on Ubuntu 20.04 (WSL on Windows),
- GCC 11.2.0 & GDB 12.0.90 on Ubuntu 22.04,
- and on current GDB HEAD (commit 8e037eae6823caf5b9cb5b4feb3de838abb25956).

Please see the attachment for the testing files.

Commands to reproduce:

	gcc -g test.c
	gdb a.out
	(gdb) set can-use-hw-watchpoints 0
	(gdb) b main
	(gdb) r
	(gdb) source test.py
	(gdb) c
	Continuing.
	Watchpoint Hit: 1
	Watchpoint Hit: 2
	Watchpoint Hit: 3
	
	Watchpoint 2 deleted because the program has left the block in
	which its expression is valid.
	Watchpoint Hit: 4
	
	Watchpoint 2 deleted because the program has left the block in
	which its expression is valid.
	Watchpoint Hit: 5
	
	Watchpoint 2 deleted because the program has left the block in
	which its expression is valid.
	Watchpoint Hit: 6
	
	...
	
	Watchpoint 2 deleted because the program has left the block in
	which its expression is valid.
	Watchpoint Hit: 1201
	
	Watchpoint 2 deleted because the program has left the block in
	which its expression is valid.
	Watchpoint Hit: 1202
	
	Watchpoint 2 deleted because the program has left the block in
	which its expression is valid.
	Watchpoint Hit: 1203
	[Inferior 1 (process 17119) exited normally]

Please note that the Watchpoint in the test file should only be hit 4 times.

I'm currently working on a patch to fix this bug.
Comment 1 Johnson Sun 2022-09-23 08:04:12 UTC
Created attachment 14352 [details]
Test C code
Comment 2 Johnson Sun 2022-09-23 08:04:41 UTC
Created attachment 14353 [details]
Test Python code
Comment 3 Johnson Sun 2022-09-25 05:36:37 UTC
Just send a patch to fix this issue. Please refer to: https://sourceware.org/pipermail/gdb-patches/2022-September/192098.html
Comment 4 Sourceware Commits 2023-05-11 16:10:08 UTC
The master branch has been updated by Simon Marchi <simark@sourceware.org>:

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=6e96d8a9702d1fef3eb6de47bb84bdea578eb1bb

commit 6e96d8a9702d1fef3eb6de47bb84bdea578eb1bb
Author: Johnson Sun <j3.soon777@gmail.com>
Date:   Thu May 11 23:46:20 2023 +0800

    Disable out-of-scope watchpoints
    
    Currently, when a local software watchpoint goes out of scope, GDB sets
    the watchpoint's disposition to `delete at next stop' and then normal
    stops (i.e., stop and wait for the next GDB command). When GDB normal
    stops, it automatically deletes the breakpoints with their disposition
    set to `delete at next stop'.
    
    Suppose a Python script decides not to normal stop when a local
    software watchpoint goes out of scope, the watchpoint will not be
    automatically deleted even when its disposition is set to
    `delete at next stop'.
    
    Since GDB single-steps the program and tests the watched expression
    after each instruction, not deleting the watchpoint causes the
    watchpoint to be hit many more times than it should, as reported in
    PR python/29603.
    
    This was happening because the watchpoint is not deleted or disabled
    when going out of scope.
    
    This commit fixes this issue by disabling the watchpoint when going out
    of scope. It also adds a test to ensure this feature isn't regressed in
    the future.
    
    Calling `breakpoint_auto_delete' on all kinds of stops (in
    `fetch_inferior_event') seem to solve this issue, but is in fact
    inappropriate, since `breakpoint_auto_delete' goes over all breakpoints
    instead of just going through the bpstat chain (which only contains the
    breakpoints that were hit right now).
    
    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29603
    Change-Id: Ia85e670b2bcba2799219abe4b6be3b582387e383
Comment 5 Hannes Domani 2024-01-14 14:26:13 UTC
(In reply to Sourceware Commits from comment #4)
> The master branch has been updated by Simon Marchi <simark@sourceware.org>:
> 
> https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;
> h=6e96d8a9702d1fef3eb6de47bb84bdea578eb1bb
> 
> commit 6e96d8a9702d1fef3eb6de47bb84bdea578eb1bb
> Author: Johnson Sun <j3.soon777@gmail.com>
> Date:   Thu May 11 23:46:20 2023 +0800
> 
>     Disable out-of-scope watchpoints
>     
>     Currently, when a local software watchpoint goes out of scope, GDB sets
>     the watchpoint's disposition to `delete at next stop' and then normal
>     stops (i.e., stop and wait for the next GDB command). When GDB normal
>     stops, it automatically deletes the breakpoints with their disposition
>     set to `delete at next stop'.
>     
>     Suppose a Python script decides not to normal stop when a local
>     software watchpoint goes out of scope, the watchpoint will not be
>     automatically deleted even when its disposition is set to
>     `delete at next stop'.
>     
>     Since GDB single-steps the program and tests the watched expression
>     after each instruction, not deleting the watchpoint causes the
>     watchpoint to be hit many more times than it should, as reported in
>     PR python/29603.
>     
>     This was happening because the watchpoint is not deleted or disabled
>     when going out of scope.
>     
>     This commit fixes this issue by disabling the watchpoint when going out
>     of scope. It also adds a test to ensure this feature isn't regressed in
>     the future.
>     
>     Calling `breakpoint_auto_delete' on all kinds of stops (in
>     `fetch_inferior_event') seem to solve this issue, but is in fact
>     inappropriate, since `breakpoint_auto_delete' goes over all breakpoints
>     instead of just going through the bpstat chain (which only contains the
>     breakpoints that were hit right now).
>     
>     Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29603
>     Change-Id: Ia85e670b2bcba2799219abe4b6be3b582387e383

Can this be closed?
Comment 6 Johnson Sun 2024-01-24 14:04:22 UTC
(In reply to Hannes Domani from comment #5)
> (In reply to Sourceware Commits from comment #4)
> > The master branch has been updated by Simon Marchi <simark@sourceware.org>:
> > 
> > https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;
> > h=6e96d8a9702d1fef3eb6de47bb84bdea578eb1bb
> > 
> > commit 6e96d8a9702d1fef3eb6de47bb84bdea578eb1bb
> > Author: Johnson Sun <j3.soon777@gmail.com>
> > Date:   Thu May 11 23:46:20 2023 +0800
> > 
> >     Disable out-of-scope watchpoints
> >     
> >     Currently, when a local software watchpoint goes out of scope, GDB sets
> >     the watchpoint's disposition to `delete at next stop' and then normal
> >     stops (i.e., stop and wait for the next GDB command). When GDB normal
> >     stops, it automatically deletes the breakpoints with their disposition
> >     set to `delete at next stop'.
> >     
> >     Suppose a Python script decides not to normal stop when a local
> >     software watchpoint goes out of scope, the watchpoint will not be
> >     automatically deleted even when its disposition is set to
> >     `delete at next stop'.
> >     
> >     Since GDB single-steps the program and tests the watched expression
> >     after each instruction, not deleting the watchpoint causes the
> >     watchpoint to be hit many more times than it should, as reported in
> >     PR python/29603.
> >     
> >     This was happening because the watchpoint is not deleted or disabled
> >     when going out of scope.
> >     
> >     This commit fixes this issue by disabling the watchpoint when going out
> >     of scope. It also adds a test to ensure this feature isn't regressed in
> >     the future.
> >     
> >     Calling `breakpoint_auto_delete' on all kinds of stops (in
> >     `fetch_inferior_event') seem to solve this issue, but is in fact
> >     inappropriate, since `breakpoint_auto_delete' goes over all breakpoints
> >     instead of just going through the bpstat chain (which only contains the
> >     breakpoints that were hit right now).
> >     
> >     Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29603
> >     Change-Id: Ia85e670b2bcba2799219abe4b6be3b582387e383
> 
> Can this be closed?

Yes, this can be closed. Thank you for the reminder.