Skip to content

Commit 62b4f94

Browse files
committed
Add option to resume at trigger breakpoints
This commit introduces an option to resume the virtual machine execution once a trigger breakpoint is hit. This allows trigger breakpoints to act as barriers for other breakpoints, enabling less priority breakpoints to remain active without requiring them to be disabled. Fixes #614
1 parent 73e3f47 commit 62b4f94

File tree

9 files changed

+71
-9
lines changed

9 files changed

+71
-9
lines changed

org.eclipse.jdt.debug.tests/tests/org/eclipse/jdt/debug/tests/breakpoints/TriggerPointBreakpointsTests.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2016 IBM Corporation and others.
2+
* Copyright (c) 2016, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -14,6 +14,7 @@
1414
package org.eclipse.jdt.debug.tests.breakpoints;
1515

1616
import org.eclipse.debug.core.model.IVariable;
17+
import org.eclipse.jdt.debug.core.IJavaBreakpoint;
1718
import org.eclipse.jdt.debug.core.IJavaLineBreakpoint;
1819
import org.eclipse.jdt.debug.core.IJavaPrimitiveValue;
1920
import org.eclipse.jdt.debug.core.IJavaStackFrame;
@@ -69,4 +70,25 @@ public void testTriggerPointBreakpoint() throws Exception {
6970
removeAllBreakpoints();
7071
}
7172
}
73+
74+
public void testTriggerPointBreakpointWithResume() throws Exception {
75+
String typeName = "TriggerPoint_01";
76+
IJavaLineBreakpoint bp1 = createLineBreakpoint(20, typeName);
77+
IJavaLineBreakpoint bp2 = createLineBreakpoint(21, typeName);
78+
bp1.setTriggerPoint(true);
79+
bp1.setSuspendPolicy(IJavaBreakpoint.RESUME_THREAD); // Resume mode
80+
IJavaThread thread = null;
81+
try {
82+
thread = launchToLineBreakpoint(typeName, bp2);
83+
84+
IJavaStackFrame frame = (IJavaStackFrame) thread.getTopStackFrame();
85+
int lineNumber = frame.getLineNumber();
86+
assertEquals("Breakpoint should resume and hit next breakpoint", 21, lineNumber);
87+
bp1.delete();
88+
bp2.delete();
89+
} finally {
90+
terminateAndRemove(thread);
91+
removeAllBreakpoints();
92+
}
93+
}
7294
}

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ public class DebugUIMessages extends NLS {
178178
public static String JDIModelPresentation_target_suspended;
179179
public static String JDIModelPresentation_thread_filtered;
180180
public static String JDIModelPresentation_uncaught_62;
181+
public static String JDIModelPresentation_Resume_VM;
181182

182183
// thread label keys are built programmatically
183184

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/DebugUIMessages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ JDIModelPresentation_modification_72=\ [modification]
117117
JDIModelPresentation_native_method=[native method]
118118
JDIModelPresentation_not_available=not available
119119
JDIModelPresentation_Suspend_VM=[Suspend VM]
120+
JDIModelPresentation_Resume_VM=[Ignored]
120121

121122
###############################################################################
122123
# Thread label keys are built programmatically

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/JDIModelPresentation.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1995,6 +1995,10 @@ protected void appendSuspendPolicy(IJavaBreakpoint breakpoint, StringBuilder buf
19951995
buffer.append(' ');
19961996
buffer.append(DebugUIMessages.JDIModelPresentation_Suspend_VM);
19971997
}
1998+
if (breakpoint.getSuspendPolicy() == IJavaBreakpoint.RESUME_THREAD) {
1999+
buffer.append(' ');
2000+
buffer.append(DebugUIMessages.JDIModelPresentation_Resume_VM);
2001+
}
19982002
}
19992003

20002004
protected void appendThreadFilter(IJavaBreakpoint breakpoint, StringBuilder buffer) throws CoreException {

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/breakpoints/StandardJavaBreakpointEditor.java

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2009, 2016 IBM Corporation and others.
2+
* Copyright (c) 2009, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -44,6 +44,7 @@ public class StandardJavaBreakpointEditor extends AbstractJavaBreakpointEditor {
4444
private Button fHitCountButton;
4545
private Text fHitCountText;
4646
private Button fSuspendThread;
47+
private Button fResumeProgram;
4748
private Button fSuspendVM;
4849
protected Button fTriggerPointButton;
4950

@@ -94,11 +95,12 @@ protected void createTriggerPointButton(Composite parent) {
9495
fTriggerPointButton.addSelectionListener(new SelectionAdapter() {
9596
@Override
9697
public void widgetSelected(SelectionEvent event) {
98+
if (isTriggerPoint()) {
99+
fResumeProgram.setSelection(false);
100+
}
97101
setDirty(PROP_TRIGGER_POINT);
98102
}
99-
100103
});
101-
102104
}
103105

104106
protected Control createStandardControls(Composite parent) {
@@ -125,12 +127,15 @@ public void modifyText(ModifyEvent e) {
125127
setDirty(PROP_HIT_COUNT);
126128
}
127129
});
130+
128131
SWTFactory.createLabel(composite, "", 1); // spacer //$NON-NLS-1$
129-
Composite radios = SWTFactory.createComposite(composite, composite.getFont(), 2, 1, GridData.FILL_HORIZONTAL, 0, 0);
132+
Composite radios = SWTFactory.createComposite(composite, composite.getFont(), 3, 1, GridData.FILL_HORIZONTAL, 0, 0);
130133
fSuspendThread = SWTFactory.createRadioButton(radios, processMnemonics(PropertyPageMessages.JavaBreakpointPage_7), 1);
131134
fSuspendThread.setLayoutData(new GridData());
132135
fSuspendVM = SWTFactory.createRadioButton(radios, processMnemonics(PropertyPageMessages.JavaBreakpointPage_8), 1);
133136
fSuspendVM.setLayoutData(new GridData());
137+
fResumeProgram = SWTFactory.createRadioButton(radios, PropertyPageMessages.BreakpointResume, 1);
138+
fResumeProgram.setLayoutData(new GridData());
134139
fSuspendThread.addSelectionListener(new SelectionAdapter() {
135140
@Override
136141
public void widgetSelected(SelectionEvent e) {
@@ -143,6 +148,13 @@ public void widgetSelected(SelectionEvent e) {
143148
setDirty(PROP_SUSPEND_POLICY);
144149
}
145150
});
151+
fResumeProgram.addSelectionListener(new SelectionAdapter() {
152+
@Override
153+
public void widgetSelected(SelectionEvent e) {
154+
setDirty(PROP_SUSPEND_POLICY);
155+
}
156+
});
157+
146158
composite.addDisposeListener(new DisposeListener() {
147159
@Override
148160
public void widgetDisposed(DisposeEvent e) {
@@ -189,6 +201,7 @@ protected void setBreakpoint(IJavaBreakpoint breakpoint) throws CoreException {
189201
boolean hasHitCount = false;
190202
String text = Util.ZERO_LENGTH_STRING;
191203
boolean suspendThread = true;
204+
boolean resume = false;
192205
if (breakpoint != null) {
193206
enabled = true;
194207
int hitCount = breakpoint.getHitCount();
@@ -197,15 +210,18 @@ protected void setBreakpoint(IJavaBreakpoint breakpoint) throws CoreException {
197210
hasHitCount = true;
198211
}
199212
suspendThread= breakpoint.getSuspendPolicy() == IJavaBreakpoint.SUSPEND_THREAD;
213+
resume = breakpoint.getSuspendPolicy() == IJavaBreakpoint.RESUME_THREAD && isTriggerPoint();
200214
}
201215
fHitCountButton.setEnabled(enabled);
202216
fHitCountButton.setSelection(enabled && hasHitCount);
203217
fHitCountText.setEnabled(hasHitCount);
204218
fHitCountText.setText(text);
205219
fSuspendThread.setEnabled(enabled);
206220
fSuspendVM.setEnabled(enabled);
207-
fSuspendThread.setSelection(suspendThread);
208-
fSuspendVM.setSelection(!suspendThread);
221+
fResumeProgram.setEnabled(isTriggerPoint());
222+
fResumeProgram.setSelection(resume);
223+
fSuspendThread.setSelection(suspendThread && !resume);
224+
fSuspendVM.setSelection(!suspendThread && !resume);
209225
fTriggerPointButton.setEnabled(enabled);
210226
fTriggerPointButton.setSelection(isTriggerPoint());
211227
setDirty(false);
@@ -238,6 +254,9 @@ public void doSave() throws CoreException {
238254
if(fSuspendVM.getSelection()) {
239255
suspendPolicy = IJavaBreakpoint.SUSPEND_VM;
240256
}
257+
if (fResumeProgram.getSelection() && isTriggerPoint() && fTriggerPointButton.isEnabled()) {
258+
suspendPolicy = IJavaBreakpoint.RESUME_THREAD;
259+
}
241260
fBreakpoint.setSuspendPolicy(suspendPolicy);
242261
int hitCount = -1;
243262
if (fHitCountButton.getSelection()) {

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2003, 2019 IBM Corporation and others.
2+
* Copyright (c) 2003, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -119,4 +119,5 @@ public class PropertyPageMessages extends NLS {
119119
public static String VMCapabilitiesPropertyPage_4;
120120
public static String VMCapabilitiesPropertyPage_6;
121121
public static String VMCapabilitiesPropertyPage_9;
122+
public static String BreakpointResume;
122123
}

org.eclipse.jdt.debug.ui/ui/org/eclipse/jdt/internal/debug/ui/propertypages/PropertyPageMessages.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,4 @@ VMCapabilitiesPropertyPage_28=&Hot Code Replace
9191
VMCapabilitiesPropertyPage_29=&Stepping
9292
VMCapabilitiesPropertyPage_30=&General
9393
VMCapabilitiesPropertyPage_31=This page displays optional debug capabilities that may be supported by the selected VM.
94+
BreakpointResume=Resume

org.eclipse.jdt.debug/model/org/eclipse/jdt/debug/core/IJavaBreakpoint.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*******************************************************************************
2-
* Copyright (c) 2000, 2016 IBM Corporation and others.
2+
* Copyright (c) 2000, 2025 IBM Corporation and others.
33
*
44
* This program and the accompanying materials
55
* are made available under the terms of the Eclipse Public License 2.0
@@ -47,6 +47,12 @@ public interface IJavaBreakpoint extends IBreakpoint, ITriggerPoint {
4747
*/
4848
public static final int SUSPEND_THREAD = 2;
4949

50+
/**
51+
* Suspend policy constant indicating a breakpoint will not suspend the target VM when hit.
52+
*
53+
* @since 3.5
54+
*/
55+
public static final int RESUME_THREAD = 3;
5056
/**
5157
* Returns whether this breakpoint is installed in at least one debug
5258
* target.

org.eclipse.jdt.debug/model/org/eclipse/jdt/internal/debug/core/model/JDIThread.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,6 +1481,13 @@ private boolean handleSuspendForBreakpointInternal(JavaBreakpoint breakpoint) {
14811481
// poll listeners without holding lock on thread
14821482
boolean suspend = true;
14831483
try {
1484+
try {
1485+
if (breakpoint.getSuspendPolicy() == IJavaBreakpoint.RESUME_THREAD) {
1486+
return false; // Won't be suspended
1487+
}
1488+
} catch (CoreException e) {
1489+
logError(e);
1490+
}
14841491
suspend = JDIDebugPlugin.getDefault().fireBreakpointHit(this,
14851492
breakpoint);
14861493
} finally {

0 commit comments

Comments
 (0)