public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Simon Marchi <simark@simark.ca>
To: Johnson Sun <j3.soon777@gmail.com>,
	Lancelot SIX <lsix@lancelotsix.com>,
	gdb-patches@sourceware.org
Subject: Re: [PATCH v3] [PR python/29603] Disable out-of-scope watchpoints
Date: Fri, 13 Jan 2023 10:40:54 -0500	[thread overview]
Message-ID: <9e6aa582-efd6-b5bf-d4b9-aebeb2e9e845@simark.ca> (raw)
In-Reply-To: <20221020181101.193226-1-j3.soon777@gmail.com>



On 10/20/22 14:11, Johnson Sun via Gdb-patches wrote:
> 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.
> 
> Two other solutions seem to solve this issue, but are in fact inappropriate:
> 1. Automatically delete breakpoints on all kinds of stops
>    (in `fetch_inferior_event'). This solution is very slow since the deletion
>    requires O(N) time for N breakpoints.
> 2. Disable the watchpoint after the watchpoint's disposition is set to
>    `delete at next stop' (in `watchpoint_del_at_next_stop'). This solution
>    modifies a non-extension-related code path, and isn't preferred since this
>    issue cannot occur without extension languages. (gdb scripts always normal
>    stop before continuing execution)

I have a bit of trouble reviewing this, because I'm not too familiar
with the lifecycle of watchpoints (I know the principle, but not the
specifically where things happen in GDB).  So it's difficult to tell
whether this is right or if there's a better way to handle it.

However, the supplied test does not pass for me:

    source /home/simark/build/binutils-gdb/gdb/testsuite/outputs/gdb.python/py-watchpoint/py-watchpoint.py
    Watchpoint 2: i
    Python script imported
    (gdb) PASS: gdb.python/py-watchpoint.exp: import python scripts
    python print(len(gdb.breakpoints()))
    2
    (gdb) PASS: gdb.python/py-watchpoint.exp: check modified BP count
    gdb_expect_list pattern: /Watchpoint Hit: ./
    continue
    Continuing.
    Watchpoint Hit: 1
    gdb_expect_list pattern: /[
    ]+Watchpoint . deleted because the program has left the block in/
    FAIL: gdb.python/py-watchpoint.exp: run until program stops (pattern 2) (timeout)
    gdb_expect_list pattern: /[
    ]+which its expression is valid./
    gdb_expect_list pattern: /Watchpoint Hit: ./
    gdb_expect_list pattern: /[
    ]+012\[Inferior 1 \(process .*\) exited normally\]/
    gdb_expect_list pattern: //
    python print(len(gdb.breakpoints()))
    Watchpoint Hit: 2
    Watchpoint Hit: 3
    Watchpoint Hit: 4

    Watchpoint 2 deleted because the program has left the block in
    which its expression is valid.
    Watchpoint Hit: 5
    012[Inferior 1 (process 2381681) exited normally]
    (gdb) FAIL: gdb.python/py-watchpoint.exp: check BP count (the program exited)

> 
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29603
> ---
>  gdb/breakpoint.c                           |  2 +
>  gdb/testsuite/gdb.python/py-watchpoint.c   | 27 ++++++++++++
>  gdb/testsuite/gdb.python/py-watchpoint.exp | 48 ++++++++++++++++++++++
>  gdb/testsuite/gdb.python/py-watchpoint.py  | 30 ++++++++++++++
>  4 files changed, 107 insertions(+)
>  create mode 100644 gdb/testsuite/gdb.python/py-watchpoint.c
>  create mode 100644 gdb/testsuite/gdb.python/py-watchpoint.exp
>  create mode 100644 gdb/testsuite/gdb.python/py-watchpoint.py
> 
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index bff3bac7d1a..15f4ae2131c 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -5340,6 +5340,8 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
>    /* Evaluate extension language breakpoints that have a "stop" method
>       implemented.  */
>    bs->stop = breakpoint_ext_lang_cond_says_stop (b);
> +  if (b->disposition == disp_del_at_next_stop)
> +    disable_breakpoint(b);

Is there a reason to do it here in particular, and not, let's say as
soon as we change the disposition to disp_del_at_next_stop?

Other question: shouldn't marking the watchpoint as
disp_del_at_next_stop make it so it won't be inserted next time we
resume?  After all should_be_inserted returns false for breakpoint
locations that are disp_del_at_next_stop.  Perhaps it's because since we
don't do a "normal" stop, breakpoint locations stay inserted, and
there's nothing that pulls this location out of the target?  Therefore,
maybe a solution, to keep things coherent, would be to pull the
breakpoint locations out when marking the breakpoint as
disp_del_at_next_stop?  This way, we would respect the invariant that a
breakpoint disp_del_at_next_stop can't be inserted (I don't know if this
is really what is happening though, it's just speculation).

And, in a broader scope, why wait until the next normal stop to delete
the watchpoint?  A "normal" stop being a stop that we present to the
user (the normal_stop function).  We currently call
breakpoint_auto_delete in normal_stop, which is why we don't reach it
when your Breakpoint.stop method returns False.  At the end of, let's
say, handle_signal_stop, could we go over the bpstat chain and delete
any breakpoint we've just hit that is marked for deletion?

Simon

  parent reply	other threads:[~2023-01-13 15:40 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-25  5:33 [PATCH] [PR python/29603] Fix deletion of Watchpoints Johnson Sun
2022-09-25 18:10 ` Lancelot SIX
2022-10-01  5:20 ` Johnson Sun
2022-10-01  5:27   ` [PATCH v2] [PR python/29603] Disable out-of-scope watchpoints Johnson Sun
2022-10-20 17:57     ` Johnson Sun
2022-10-20 18:11       ` [PATCH v3] " Johnson Sun
2022-11-18 12:17         ` [PING] " Johnson Sun
2022-11-25 15:11           ` [PING^2] " Johnson Sun
2022-12-04 16:45             ` [PING^3] " Johnson Sun
2022-12-12 21:44               ` [PING^4] " Johnson Sun
2022-12-20 22:08                 ` [PING^5] " Johnson Sun
2022-12-27 16:40                   ` [PING^6] " Johnson Sun
2023-01-12 18:34                     ` [PING^7] " Johnson Sun
2023-01-13 15:40         ` Simon Marchi [this message]
2023-01-23 10:15           ` Johnson Sun
2023-02-18 16:26             ` [PING] " Johnson Sun
2023-02-26  6:16               ` [RFC] " Johnson Sun
2023-03-12 17:24                 ` [PING] " Johnson Sun
2023-03-13 16:00             ` Simon Marchi
2023-03-23 18:25               ` Johnson Sun
2023-03-23 18:31                 ` [PATCH v4] " Johnson Sun
2023-04-09 20:47                   ` Johnson Sun
2023-04-09 20:49                     ` [PING] " Johnson Sun
2023-04-17 18:18                       ` [PING^2] " Johnson Sun
2023-04-17 18:56                   ` Simon Marchi
2023-04-23  9:46                     ` Johnson Sun
2023-04-23  9:54                       ` [PATCH v5] " Johnson Sun
2023-05-06 19:06                         ` [PING] " Johnson Sun
2023-05-09 18:50                         ` Simon Marchi
2023-05-10 17:22                           ` Johnson Sun
2023-05-11  2:08                             ` Simon Marchi
2023-05-11 15:46                               ` [PATCH v6] " Johnson Sun
2023-05-11 16:09                                 ` Simon Marchi
2023-05-11 15:50                               ` [PATCH v5] " Johnson Sun

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9e6aa582-efd6-b5bf-d4b9-aebeb2e9e845@simark.ca \
    --to=simark@simark.ca \
    --cc=gdb-patches@sourceware.org \
    --cc=j3.soon777@gmail.com \
    --cc=lsix@lancelotsix.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).