Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 314865 - When "Skip All Breakpoints" is ticked breakpoints at launch can be hit
Summary: When "Skip All Breakpoints" is ticked breakpoints at launch can be hit
Status: RESOLVED FIXED
Alias: None
Product: CDT
Classification: Tools
Component: cdt-debug-cdi-gdb (show other bugs)
Version: 7.0   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 7.0.1   Edit
Assignee: James Blackburn CLA
QA Contact: Elena Laskavaia CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-05-28 09:27 EDT by James Blackburn CLA
Modified: 2010-06-25 05:23 EDT (History)
3 users (show)

See Also:
jamesblackburn+eclipse: review? (nobody)
john.cortell: review+


Attachments
Skip All breakpoints selected (11.27 KB, text/plain)
2010-05-28 09:27 EDT, James Blackburn CLA
no flags Details
Individually disabled (10.25 KB, text/plain)
2010-05-28 09:27 EDT, James Blackburn CLA
no flags Details
patch 1 (4.29 KB, patch)
2010-05-28 11:43 EDT, James Blackburn CLA
jamesblackburn+eclipse: iplog-
Details | Diff
additional tidy (2.14 KB, patch)
2010-05-28 12:37 EDT, James Blackburn CLA
jamesblackburn+eclipse: iplog-
Details | Diff
patch 2 (5.96 KB, patch)
2010-06-23 13:36 EDT, James Blackburn CLA
jamesblackburn+eclipse: iplog-
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description James Blackburn CLA 2010-05-28 09:27:14 EDT
Created attachment 170340 [details]
Skip All breakpoints selected

This seems to be caused by a commit referencing bug 79371.

If the user has "Skip All Breakpoints" toggled then the breakpoints are disabled asynchronously as part of a MIBreakpointCreatedEvent.  The result is they can be hit before being disabled on launch.

It's reasonably easy to reproduce:
 - Create helloworld app
 - double click in the margin to set a breakpoint at every line
 - Enable "Skip all breakpoints" in the breakpoint view
 - launch
 - The mi log shows that the breakpoint is created and occurs long before the disable command is sent

If the breakpoints are physically disabled by deselecting them, then they're disabled as soon as they're set.

MILogs attached.
Comment 1 James Blackburn CLA 2010-05-28 09:27:50 EDT
Created attachment 170341 [details]
Individually disabled
Comment 2 James Blackburn CLA 2010-05-28 11:10:06 EDT
Another interesting failure case of this async disable on created:

	while (1) {
		puts("!!!Hello World!!!"); /* prints !!!Hello World!!! */
	}

Turn on Skip All Breakpoints and double click in the margin rapidly. Eventually you can get the target to stop at the breakpoint.

I think the solution is to disable the breakpoint on creation like we do if the breakpoint marker isn't enabled. That way we don't have this race.  There's then no need to disable asynchronously after a created event.
Comment 3 James Blackburn CLA 2010-05-28 11:43:41 EDT
Created attachment 170368 [details]
patch 1

Patch for the issue:

BreakpointManager:
  - When the backend CDI breakpoint is created: 
    disable it if !DebugPlugin.getDefault().getBreakpointManager().isEnabled(). This is the same as if the breakpoint marker is disabled.
  - If disabling the breakpoint on creation, we should mark it as disabled (or we'll be out of sync for re-enabling...) 

CBreakpointManager:
  - No need to changeBreakpointPropertiesOnTarget on creation event, as the enablement is now correct.
  - changeBreakpointProperties, should consider DebugPlugin.getDefault().getBreakpointManager().isEnabled when setting CDI backend breakpoint enablement

Mikhail, AFAICS it's entirely redundant to check enablement in:
	private void CBreakpointManager#changeBreakpointProperties( ICBreakpoint breakpoint, ICDIBreakpoint cdiBreakpoint )
Presumably the condition state is up to date here too...?
Comment 4 James Blackburn CLA 2010-05-28 11:43:59 EDT
Mikhail can you take a look?
Comment 5 James Blackburn CLA 2010-05-28 12:37:52 EDT
Created attachment 170380 [details]
additional tidy

(In reply to comment #3)
> Mikhail, AFAICS it's entirely redundant to check enablement in:
>     private void CBreakpointManager#changeBreakpointProperties( ICBreakpoint
> breakpoint, ICDIBreakpoint cdiBreakpoint )
> Presumably the condition state is up to date here too...?

AFAICS as changeBreakpointProperties( ICBreakpoint breakpoint, ICDIBreakpoint cdiBreakpoint ) is only called on the breakpoint created event, and given that enablement and condition are correct at this point, this method is redundant?

Am I missing something?
Comment 6 James Blackburn CLA 2010-05-28 13:23:02 EDT
John CVS shows you've done some work on CDI breakpoints, if you could look over these patches for post 7 I'd be grateful.
Comment 7 John Cortell CLA 2010-06-02 14:25:59 EDT
(In reply to comment #6)
> John CVS shows you've done some work on CDI breakpoints, if you could look over
> these patches for post 7 I'd be grateful.

Does this change reintroduce the issue resolved by bug 79371. If so, then it seems the first step should be having Mikhail evaluate the solution. It seems to me that the problem of breakpoints being hit that shouldn't be is a more serious one than that of sluggishness (79371). But before investing time in reviewing the fix, I'd like Mikhail to chime in.
Comment 8 James Blackburn CLA 2010-06-02 15:05:28 EDT
I don't believe it does reintroduce bug 79371.  All breakpoints are inserted at launch anyway. The change in the patch is just to set the enablement appropriately taking into account the global disable switch.   

This then led to the 'additional tidy' as I can't see why on breakpoint created we need to check whether enablement and condition are correct.  Presumably these are always correct after creation...  I'll take another look to see if the created event can be fired in some other way, but when I looked, it the additional check seemed superfluous...

The patch is in my product, but for CDT this is deferred past 7. Input from you guys would be appreciated!
Comment 9 Nobody - feel free to take it CLA 2010-06-02 15:21:15 EDT
(In reply to comment #8)
> The patch is in my product, but for CDT this is deferred past 7. Input from you
> guys would be appreciated!
James, I am really busy this week. But I'll try to review it next week.
Comment 10 John Cortell CLA 2010-06-02 16:25:47 EDT
James, I think it would be better to take into account the 'skip all breakpoints' global state when creating the CDI breakpoint object (in CBreakpointManager.setBreakpointsOnTarget0()). This will provide more consistent behavior. Consider the case where 

(a) the CDI client doesn't support ICDIBreakpointManagement2; i.e., you can't pass the enable flag when creating the CDI breakpoint
(b) the 'skip' state if off
(c) the breakpoint is disabled

In that case, even with your changes, the breakpoint won't be disabled in the backend until 

   b.setEnabled( icbreakpoint.isEnabled() ); 

is called in CBreakpointManager. Yet, your changes will provide specialized behavior if the 'skip' state is turned on. It will behave as if the client implemented ICDIBreakpointManagement2, and that inconsistency can only lead to subtle problems or differences in behavior.

Again, if you just consider the 'skip' state within CBreakpointManager.setBreakpointsOnTarget0(), everything should just play out nicely and you won't need any of the logic you added in BreakpointManager.
Comment 11 James Blackburn CLA 2010-06-03 12:47:12 EDT
(In reply to comment #10)
> James, I think it would be better to take into account the 'skip all
> breakpoints' global state when creating the CDI breakpoint object (in
> CBreakpointManager.setBreakpointsOnTarget0()). 

Thanks John! I'm quite inexperienced in this code and easily get lost between debug.core and debug.mi.core (and in the various C*Managers vs *Managers...).  Hopefully I'll get a chance to revisit this over the next couple days or so.
Comment 12 James Blackburn CLA 2010-06-23 13:36:15 EDT
Created attachment 172535 [details]
patch 2

An updated patch as per John's comment:
In CBreakpointManager#setBreakpointsOnTarget0(...) the created CDIBreakpoint has it's initial enablement set to marker.enabled && breakpointManager.isEnabled(). This should then work correctly for all breakpoint manager backends.

There are a couple other places which consider the breapoint marker (ICBreakpoint) enablement, reconciling the ICDIbreakpoint enablement appropriately.  As marker enablement is orthogonal to Global breakpoint manager enablement, these places need to consider that. Specifically:
   - #changeBreakpointProperties(IMarkerDelta...)
   - #changeBreakpointProperties(ICBreakpoint, ICDIBreakpoint)

It still feels clunky having created a breakpoint (at startup), that we need to check the enablement is ok. However I can believe that this is needed for handling cli created breakpoints.

I've tested:
  - Staring a debug session with breakpoints globally disabled, then globally enabling
  - Repeatedly destroying and recreating the breakpoint marker
  - Repeatedly disabling and re-enabling the breakpoint marker
  - interrupting the target (with breakpoints globally disabled), creating a new breakpoint with the CLI, and resuming.  Target doesn't stop on resume. Correctly stops when the global disable is unset.

+ other combination of changing the marker, toggling the global enablement, and using the CLI

John + Mikhail please take a look if you get a chance
Comment 13 John Cortell CLA 2010-06-24 18:24:49 EDT
Looks good to me, James.
Comment 14 James Blackburn CLA 2010-06-25 04:37:09 EDT
Committed to HEAD & 7.0.1. Thanks John.