From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19610 invoked by alias); 1 Oct 2013 11:32:09 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 19596 invoked by uid 89); 1 Oct 2013 11:32:08 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 01 Oct 2013 11:32:08 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.3 required=5.0 tests=AWL,BAYES_00,RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from int-mx12.intmail.prod.int.phx2.redhat.com (int-mx12.intmail.prod.int.phx2.redhat.com [10.5.11.25]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r91BW6cI002470 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 1 Oct 2013 07:32:06 -0400 Received: from localhost.localdomain (ovpn-112-31.ams2.redhat.com [10.36.112.31]) by int-mx12.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r91BW4Dk003157; Tue, 1 Oct 2013 07:32:05 -0400 Message-ID: <524AB2B3.2040301@redhat.com> Date: Tue, 01 Oct 2013 11:32:00 -0000 From: Phil Muldoon MIME-Version: 1.0 To: Tom Tromey CC: gdb-patches@sourceware.org Subject: Re: [python][patch] Add temporary breakpoint features to Python breakpoints. References: <522D9D57.5030309@redhat.com> <87r4cxj0i3.fsf@fleche.redhat.com> <52396DC3.4090104@redhat.com> In-Reply-To: <52396DC3.4090104@redhat.com> Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-IsSubscribed: yes X-SW-Source: 2013-10/txt/msg00035.txt.bz2 On 18/09/13 10:09, Phil Muldoon wrote: > On 09/09/13 19:47, Tom Tromey wrote: >>>>>>> "Phil" == Phil Muldoon writes: > >> Phil> 2013-09-09 Phil Muldoon >> >> Phil> * python/py-breakpoint.c (bppy_get_temporary): New function. >> Phil> (bppy_init): New keyword: temporary. Parse it and set breakpoint >> Phil> to temporary if True. >> >> Is there a PR associated with this? >> I thought there was, but I didn't check. > > I did a search and I could not find one. > >> In particular I was wondering how it interacts with the "stop" method. > > I added a test to make sure the "stop" method is executing before > deletion. I think the docs are approved by both you and Eli? > > Other nits fixed up too. ChangeLog remains the same. > > OK? > > Cheers, > > Phil Ping Cheers, Phil > -- > > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index 21250fe..627d65e 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -26799,22 +26799,27 @@ Return the static block of the underlying symbol table. > Python code can manipulate breakpoints via the @code{gdb.Breakpoint} > class. > > -@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[},internal@r{]]]}) > -Create a new breakpoint. @var{spec} is a string naming the > -location of the breakpoint, or an expression that defines a > -watchpoint. The contents can be any location recognized by the > -@code{break} command, or in the case of a watchpoint, by the @code{watch} > -command. The optional @var{type} denotes the breakpoint to create > -from the types defined later in this chapter. This argument can be > -either: @code{gdb.BP_BREAKPOINT} or @code{gdb.BP_WATCHPOINT}. @var{type} > -defaults to @code{gdb.BP_BREAKPOINT}. The optional @var{internal} argument > -allows the breakpoint to become invisible to the user. The breakpoint > -will neither be reported when created, nor will it be listed in the > -output from @code{info breakpoints} (but will be listed with the > -@code{maint info breakpoints} command). The optional @var{wp_class} > -argument defines the class of watchpoint to create, if @var{type} is > -@code{gdb.BP_WATCHPOINT}. If a watchpoint class is not provided, it is > -assumed to be a @code{gdb.WP_WRITE} class. > +@defun Breakpoint.__init__ (spec @r{[}, type @r{[}, wp_class @r{[},internal @r{[},temporary@r{]]]]}) > +Create a new breakpoint. @var{spec} is a string naming the location > +of the breakpoint, or an expression that defines a watchpoint. The > +contents can be any location recognized by the @code{break} command, > +or in the case of a watchpoint, by the @code{watch} command. The > +optional @var{type} denotes the breakpoint to create from the types > +defined later in this chapter. This argument can be either: > +@code{gdb.BP_BREAKPOINT} or @code{gdb.BP_WATCHPOINT}. @var{type} > +defaults to @code{gdb.BP_BREAKPOINT}. The optional @var{internal} > +argument allows the breakpoint to become invisible to the user. The > +breakpoint will neither be reported when created, nor will it be > +listed in the output from @code{info breakpoints} (but will be listed > +with the @code{maint info breakpoints} command). The optional > +@var{temporary} argument makes the breakpoint a temporary breakpoint. > +Temporary breakpoints are deleted after they have been hit. Any > +further access to the Python breakpoint after it has been hit will > +result in a runtime error (as that breakpoint has now been > +automatically deleted). The optional @var{wp_class} argument defines > +the class of watchpoint to create, if @var{type} is > +@code{gdb.BP_WATCHPOINT}. If a watchpoint class is not provided, it > +is assumed to be a @code{gdb.WP_WRITE} class. > @end defun > > @defun Breakpoint.stop (self) > @@ -26935,6 +26940,16 @@ when set, or when the @samp{info breakpoints} command is run. This > attribute is not writable. > @end defvar > > +@defvar Breakpoint.temporary > +This attribute indicates whether the breakpoint was created as a > +temporary breakpoint. Temporary breakpoints are automatically deleted > +after that breakpoint has been hit. Access to this attribute, and all > +other attributes and functions other than the @code{is_valid} > +function, will result in an error after the breakpoint has been hit > +(as it has been automatically deleted). This attribute is not > +writable. > +@end defvar > + > The available types are represented by constants defined in the @code{gdb} > module: > > diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c > index 87f1fdc..e83471e 100644 > --- a/gdb/python/py-breakpoint.c > +++ b/gdb/python/py-breakpoint.c > @@ -529,6 +529,23 @@ bppy_get_visibility (PyObject *self, void *closure) > Py_RETURN_TRUE; > } > > +/* Python function to determine if the breakpoint is a temporary > + breakpoint. */ > + > +static PyObject * > +bppy_get_temporary (PyObject *self, void *closure) > +{ > + breakpoint_object *self_bp = (breakpoint_object *) self; > + > + BPPY_REQUIRE_VALID (self_bp); > + > + if (self_bp->bp->disposition == disp_del > + || self_bp->bp->disposition == disp_del_at_next_stop) > + Py_RETURN_TRUE; > + > + Py_RETURN_FALSE; > +} > + > /* Python function to get the breakpoint's number. */ > static PyObject * > bppy_get_number (PyObject *self, void *closure) > @@ -594,16 +611,20 @@ bppy_get_ignore_count (PyObject *self, void *closure) > static int > bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) > { > - static char *keywords[] = { "spec", "type", "wp_class", "internal", NULL }; > + static char *keywords[] = { "spec", "type", "wp_class", "internal", > + "temporary", NULL }; > const char *spec; > int type = bp_breakpoint; > int access_type = hw_write; > PyObject *internal = NULL; > + PyObject *temporary = NULL; > int internal_bp = 0; > + int temporary_bp = 0; > volatile struct gdb_exception except; > > - if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiO", keywords, > - &spec, &type, &access_type, &internal)) > + if (! PyArg_ParseTupleAndKeywords (args, kwargs, "s|iiOO", keywords, > + &spec, &type, &access_type, > + &internal, &temporary)) > return -1; > > if (internal) > @@ -613,6 +634,13 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) > return -1; > } > > + if (temporary != NULL) > + { > + temporary_bp = PyObject_IsTrue (temporary); > + if (temporary_bp == -1) > + return -1; > + } > + > bppy_pending_object = (breakpoint_object *) self; > bppy_pending_object->number = -1; > bppy_pending_object->bp = Tom Tromey NULL; > @@ -629,7 +657,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs) > create_breakpoint (python_gdbarch, > copy, NULL, -1, NULL, > 0, > - 0, bp_breakpoint, > + temporary_bp, bp_breakpoint, > 0, > AUTO_BOOLEAN_TRUE, > &bkpt_breakpoint_ops, > @@ -973,6 +1001,8 @@ or None if no condition set."}, > "Type of breakpoint."}, > { "visible", bppy_get_visibility, NULL, > "Whether the breakpoint is visible to the user."}, > + { "temporary", bppy_get_temporary, NULL, > + "Whether this breakpoint is a temporary breakpoint."}, > { NULL } /* Sentinel. */ > }; > > diff --git a/gdb/testsuite/gdb.python/py-breakpoint.exp b/gdb/testsuite/gdb.python/py-breakpoint.exp > index 687182d..e2a169b 100644 > --- a/gdb/testsuite/gdb.python/py-breakpoint.exp > +++ b/gdb/testsuite/gdb.python/py-breakpoint.exp > @@ -300,3 +300,37 @@ gdb_py_test_silent_cmd "python wp1 = wp_eval (\"result\", type=gdb.BP_WATCHPOIN > gdb_test "continue" ".*\[Ww\]atchpoint.*result.*Old value =.*New value = 788.*" "Test watchpoint write" > gdb_test "python print (never_eval_bp1.count)" "0" \ > "Check that this unrelated breakpoints eval function was never called." > + > +# Test temporary breakpoint > + > +# Start with a fresh gdb. > +clean_restart ${testfile} > + > +if ![runto_main] then { > + fail "Cannot run to main." > + return 0 > +} > +delete_breakpoints > +gdb_py_test_multiple "Sub-class and check temporary breakpoint" \ > + "python" "" \ > + "class temp_bp (gdb.Breakpoint):" "" \ > + " count = 0" "" \ > + " def stop (self):" "" \ > + " self.count = self.count + 1" "" \ > + " return True" "" \ > + "end" "" > +gdb_py_test_silent_cmd "python ibp = temp_bp(\"$ibp_location\", temporary=True)" \ > + "Set temporary breakpoint" 0 > +gdb_test "info breakpoints" "2.*breakpoint.*del.*py-breakpoint\.c:$ibp_location.*" \ > + "Check info breakpoints shows breakpoint with temporary status" > +gdb_test "python print (ibp.location)" "py-breakpoint\.c:$ibp_location*" \ > + "Check temporary breakpoint location" > +gdb_test "python print (ibp.temporary)" "True" \ > + "Check breakpoint temporary status" > +gdb_continue_to_breakpoint "Break at multiply." ".*/$srcfile:$ibp_location.*" > +gdb_test "python print (ibp.count)" "1" \ > + "Check temporary stop callback executed before deletion." > +gdb_test "python print (ibp.temporary)" "RuntimeError: Breakpoint 2 is invalid.*" \ > + "Check temporary breakpoint is deleted after being hit" > +gdb_test "info breakpoints" "No breakpoints or watchpoints.*" \ > + "Check info breakpoints shows temporary breakpoint is deleted" > >