Skip to content

Commit 4381ef5

Browse files
basilevslaeubi
authored andcommitted
Do not throw on launch cancel #2009
Fixes #2009. `ILaunchConfiguration.launch()` javadoc declares that ILaunch is returned even when `IProgressMonitor` argument is canceled. Before this fix, `OperationCanceledException` could be thrown instead.
1 parent 45b3862 commit 4381ef5

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

debug/org.eclipse.debug.core/core/org/eclipse/debug/internal/core/LaunchConfiguration.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import org.eclipse.core.runtime.IPath;
4646
import org.eclipse.core.runtime.IProgressMonitor;
4747
import org.eclipse.core.runtime.IStatus;
48+
import org.eclipse.core.runtime.OperationCanceledException;
4849
import org.eclipse.core.runtime.PlatformObject;
4950
import org.eclipse.core.runtime.Status;
5051
import org.eclipse.core.runtime.SubMonitor;
@@ -775,7 +776,17 @@ public ILaunch launch(String mode, IProgressMonitor monitor, boolean build, bool
775776
/* Launch the delegate */
776777
lmonitor.subTask(DebugCoreMessages.LaunchConfiguration_2);
777778
delegate.launch(this, mode, launch, lmonitor.split(10));
779+
} catch (OperationCanceledException e) {
780+
if (launch != null) {
781+
getLaunchManager().removeLaunch(launch);
782+
return launch;
783+
}
784+
throw e;
778785
} catch (CoreException e) {
786+
if (launch != null && e.getStatus().matches(IStatus.CANCEL)) {
787+
getLaunchManager().removeLaunch(launch);
788+
return launch;
789+
}
779790
// if there was an exception, and the launch is empty, remove it
780791
if (launch != null && !launch.hasChildren()) {
781792
getLaunchManager().removeLaunch(launch);

debug/org.eclipse.debug.tests/src/org/eclipse/debug/tests/launching/LaunchConfigurationTests.java

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static org.assertj.core.api.Assertions.assertThat;
1818
import static org.junit.Assert.assertEquals;
1919
import static org.junit.Assert.assertFalse;
20+
import static org.junit.Assert.assertNotEquals;
2021
import static org.junit.Assert.assertNotNull;
2122
import static org.junit.Assert.assertNotSame;
2223
import static org.junit.Assert.assertNull;
@@ -42,6 +43,7 @@
4243
import java.util.Map;
4344
import java.util.Set;
4445
import java.util.concurrent.atomic.AtomicBoolean;
46+
import java.util.concurrent.atomic.AtomicInteger;
4547

4648
import org.eclipse.core.filesystem.EFS;
4749
import org.eclipse.core.filesystem.IFileSystem;
@@ -55,7 +57,10 @@
5557
import org.eclipse.core.resources.ResourcesPlugin;
5658
import org.eclipse.core.runtime.CoreException;
5759
import org.eclipse.core.runtime.IPath;
60+
import org.eclipse.core.runtime.IProgressMonitor;
61+
import org.eclipse.core.runtime.NullProgressMonitor;
5862
import org.eclipse.core.runtime.Platform;
63+
import org.eclipse.core.runtime.Status;
5964
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
6065
import org.eclipse.core.runtime.preferences.InstanceScope;
6166
import org.eclipse.debug.core.DebugPlugin;
@@ -64,9 +69,11 @@
6469
import org.eclipse.debug.core.ILaunchConfigurationListener;
6570
import org.eclipse.debug.core.ILaunchConfigurationType;
6671
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
72+
import org.eclipse.debug.core.ILaunchDelegate;
6773
import org.eclipse.debug.core.ILaunchManager;
6874
import org.eclipse.debug.core.ILaunchesListener2;
6975
import org.eclipse.debug.core.Launch;
76+
import org.eclipse.debug.core.model.ILaunchConfigurationDelegate2;
7077
import org.eclipse.debug.core.model.IProcess;
7178
import org.eclipse.debug.internal.core.LaunchConfiguration;
7279
import org.eclipse.debug.internal.core.LaunchManager;
@@ -1331,6 +1338,79 @@ public void launchesTerminated(ILaunch[] launches) {
13311338
}
13321339
}
13331340

1341+
/**
1342+
* Do not return null or throw on cancel
1343+
*
1344+
* @see https://github.com/eclipse-platform/eclipse.platform/issues/2009
1345+
* @see org.eclipse.debug.core.ILaunchConfiguration#launch(String,
1346+
* IProgressMonitor)
1347+
*/
1348+
@Test
1349+
public void testCancel() throws CoreException {
1350+
final ILaunchDelegate launchDelegate = ((LaunchManager) DebugPlugin.getDefault().getLaunchManager()).getLaunchDelegate(LaunchConfigurationTests.ID_TEST_LAUNCH_TYPE);
1351+
final TestLaunchDelegate testLaunchDelegate = (TestLaunchDelegate) launchDelegate.getDelegate();
1352+
ILaunchConfigurationDelegate2 customLaunchDelegate = new ILaunchConfigurationDelegate2() {
1353+
1354+
void sleep() {
1355+
}
1356+
@Override
1357+
public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException {
1358+
sleep();
1359+
if (monitor.isCanceled()) {
1360+
throw new CoreException(Status.CANCEL_STATUS);
1361+
}
1362+
}
1363+
1364+
@Override
1365+
public boolean preLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
1366+
sleep();
1367+
return !monitor.isCanceled();
1368+
}
1369+
1370+
@Override
1371+
public ILaunch getLaunch(ILaunchConfiguration configuration, String mode) throws CoreException {
1372+
sleep();
1373+
return null;
1374+
}
1375+
1376+
@Override
1377+
public boolean finalLaunchCheck(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
1378+
sleep();
1379+
return !monitor.isCanceled();
1380+
}
1381+
1382+
@Override
1383+
public boolean buildForLaunch(ILaunchConfiguration configuration, String mode, IProgressMonitor monitor) throws CoreException {
1384+
sleep();
1385+
return !monitor.isCanceled();
1386+
}
1387+
};
1388+
testLaunchDelegate.setDelegate(customLaunchDelegate);
1389+
try {
1390+
ILaunchConfigurationWorkingCopy workingCopy = newConfiguration(null, "cancel me"); //$NON-NLS-1$
1391+
int cancelCount = 0;
1392+
for (int i = 0; i < 10_000; i++) {
1393+
AtomicInteger checkCount = new AtomicInteger(i);
1394+
NullProgressMonitor monitor = new NullProgressMonitor() {
1395+
@Override
1396+
public boolean isCanceled() {
1397+
return super.isCanceled() || checkCount.getAndDecrement() <= 0;
1398+
}
1399+
};
1400+
// Should not throw
1401+
ILaunch launch = workingCopy.launch(ILaunchManager.RUN_MODE, monitor);
1402+
assertNotNull(launch);
1403+
if (!monitor.isCanceled()) {
1404+
break;
1405+
}
1406+
cancelCount++;
1407+
}
1408+
assertNotEquals(0, cancelCount);
1409+
} finally {
1410+
testLaunchDelegate.setDelegate(null);
1411+
}
1412+
}
1413+
13341414
/**
13351415
* Tests that a launch is properly registered for notifications before a
13361416
* process is spawned and may already propagate a termination event.

0 commit comments

Comments
 (0)