On Mon, Oct 24, 2011 at 11:14 AM, Kevin Pouget wrote: > On Fri, Oct 21, 2011 at 9:45 AM, Kevin Pouget wrote: >> On Thu, Oct 20, 2011 at 10:41 PM, Tom Tromey wrote: >>>>>>>> "Kevin" == Kevin Pouget writes: >>> >>> Tom> You need to store a gdb.Type wrapper. >>> Tom> A 'struct type' can also be invalidated when an objfile is destroyed. >>> >>> Kevin> I wouldn't mind, but I can't see how gdb.Type ensures validity, as far >>> Kevin> as I've seen, there is no "is_valid" method and I can't and no further >>> Kevin> verification during the Python -> C translation: >>> >>> When an objfile is destroyed, py-type.c:save_objfile_types is called. >>> This makes a copy of the struct type underlying any relevant Type object. >> >> I'll take a look at that, I don't remember what was the problem! > > I understood that, and replaced 'struct type *' fields by the > corresponding 'PyObject/Type' python objects > >>> [ out_of_scope_notif ] >>> Kevin> - avoid calling `out_of_scope' every normal_stop when the breakpoint >>> Kevin> is not anymore in the callstack >>> >>> It seems to me that manually managing this is not the best we could do. >>> >>> I was re-reading the code and I realized that this isn't actually >>> working the way I had remembered it working: >>> >>> +A @fdb{finish breakpoint} is a breakpoint set at the return address of >>> +a frame, based on the "finish command. @code{gdb.FinishBreakpoint} extends >>> +@code{gdb.Breakpoint} >>> >>> This approach is fine; but once a frame is gone, it is gone -- we should >>> just destroy the breakpoint at that point.  Maybe this would make the >>> internal logic simpler as well. >> >> yes, I think you're right with that, "once a frame is gone, it is >> gone", I actually don't use myself this 'permanent finish breakpoint' >> feature, so I'll change it. >> So basically, the BP must be deleted right after it has been it (maybe >> through the 'temporary' mechanism). 'out_of_scope' will be triggered >> in the same conditions as before, but instead of playing with >> 'out_of_scope_notif' I'll delete the GDB breakpoint (thus invalidating >> the Python BP) >> >> I'll post a patch going this way later today > > So I've changed the way FinishBreakpoints are 'garbage collected'. > Now, they're more similar to Temporary Breakpoints, that is, they're > deleted *soon* after they've been hit. > Soon, because when Breakpoint.stop tells GDB *not* to stop at the > [finish] breakpoint, there is no way to delete this breakpoint (and I > guess that may be the reason why Temporary Breakpoints are not > available in Python yet). > > So I disable it, and "b->disposition == disp_del" will ensure that the > BP will be removed when it's possible. > > The `out_of_scope' callback will also delete the breakpoint. > > > I've updated the doc and testsuite accordingly, and as far as I've > seen, there is no regression on X86_64/Fedora > (I need still need to improve my test environment) there was indeed a little regression hidden in the middle of the testsuite logs, which made "tbreak ... if condition" fail if the condition was not satisfied at the first try. I've fixed it with: /* If it's a temporary breakpoint. */ if (bpfinishpy_is_finish_bp(py_bp)) { /* Can't delete it here. */ gdb_assert (b->disposition == disp_del); disable_breakpoint (b); } which now only affects gdb.FinishBreakpoint-s. They can be hit only once, in opposition with proper temporary breakpoints which remain until their condition succeeds. This patch also encompasses the doc modifications asked by Eli and a NEWS entry. Thanks, Kevin 2011-10-24 Kevin Pouget Introduce gdb.FinishBreakpoints in Python * Makefile.in (SUBDIR_PYTHON_OBS): Add py-finishbreakpoint.o. (SUBDIR_PYTHON_SRCS): Add python/py-finishbreakpoint.c. Add build rule for this file. * breakpoint.h (struct breakpoint): New field: is_py_finish_bp. * breakpoint.c (init_raw_breakpoint_without_location): Initialize is_py_finish_bp. * infcmd.c (get_return_value): New function. (print_return_value): Split to create get_return_value. * inferior.h (get_return_value): New prototype. * infrun.c: Include python/python.h. (stop_registers): Mention FinishBreakpoint in description. (normal_stop): Set stop_registers if stopped at FinishBreakpoint. * python/py-breakpoint.c (breakpoint_object_type): Make non-static. (bppy_pending_object): Likewise (gdbpy_should_stop): Disable temporary breakpoints. (gdbpy_breakpoint_created): Set is_py_finish_bp is necessary. (struct breakpoint_object): Move to python-internal.h (BPPY_REQUIRE_VALID): Likewise. (BPPY_SET_REQUIRE_VALID): Likewise. * python/python-internal.h (breakpoint_object_type): Add as extern. (bppy_pending_object): Likewise. (typedef struct breakpoint_object) Removed. (struct breakpoint_object): Moved from py-breakpoint.c. (BPPY_REQUIRE_VALID): Likewise. (BPPY_SET_REQUIRE_VALID): Likewise. (frame_object_to_frame_info): New prototype. (gdbpy_initialize_finishbreakpoints): New prototype. (bpfinishpy_is_finish_bp): Likewise. * python/py-finishbreakpoint.c: New file. * python/py-frame.c(frame_object_to_frame_info): Make non-static and accept PyObject instead of frame_object. (frapy_is_valid): Don't cast to frame_object. (frapy_name): Likewise. (frapy_type): Likewise. (frapy_unwind_stop_reason): Likewise. (frapy_pc): Likewise. (frapy_block): Likewise. (frapy_function): Likewise. (frapy_older): Likewise. (frapy_newer): Likewise. (frapy_find_sal): Likewise. (frapy_read_var): Likewise. (frapy_select): Likewise. * python/python.c (gdbpy_is_stopped_at_finish_bp): New noop function. (_initialize_python): Add gdbpy_initialize_finishbreakpoints. * python/python.h: Include breakpoint.h (gdbpy_is_stopped_at_finish_bp): New prototype. doc/ * gdb.texinfo (Breakpoints In Python): New subsection: Finish Breakpoints. testsuite/ * gdb.python/py-breakpoint.exp (mult_line): Define and use variable instead of line number. * gdb.python/py-finish-breakpoint.c: New file. * gdb.python/py-finish-breakpoint.exp: New file. * gdb.python/py-finish-breakpoint.py: New file. * gdb.python/py-finish-breakpoint2.cc: New file. * gdb.python/py-finish-breakpoint2.exp: New file. * gdb.python/py-finish-breakpoint2.py: New file.