Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHannes Wellmann2021-02-11 20:08:39 +0000
committerSarika Sinha2021-02-22 11:01:21 +0000
commitc239e1061cd3e02c6e3cb7f34b2be0be7fea7355 (patch)
treefaa275a7f82e7b8458cc681fd00a363bfeb520d5
parentee6cc06388c729e1abe892abd01fa0a2c271793c (diff)
downloadeclipse.platform.debug-c239e1061cd3e02c6e3cb7f34b2be0be7fea7355.tar.gz
eclipse.platform.debug-c239e1061cd3e02c6e3cb7f34b2be0be7fea7355.tar.xz
eclipse.platform.debug-c239e1061cd3e02c6e3cb7f34b2be0be7fea7355.zip
Change-Id: I6f77f33c27028c06c4afb58eae9604eeab317866 Signed-off-by: Hannes Wellmann <wellmann.hannes1@gmx.net>
-rw-r--r--org.eclipse.debug.core/META-INF/MANIFEST.MF2
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java15
-rw-r--r--org.eclipse.debug.core/core/org/eclipse/debug/core/model/RuntimeProcess.java30
-rw-r--r--org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/RuntimeProcessTests.java37
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java1
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties3
-rw-r--r--org.eclipse.debug.ui/ui/org/eclipse/debug/ui/CommonTab.java30
7 files changed, 101 insertions, 17 deletions
diff --git a/org.eclipse.debug.core/META-INF/MANIFEST.MF b/org.eclipse.debug.core/META-INF/MANIFEST.MF
index 916303bb9..08fab6d01 100644
--- a/org.eclipse.debug.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.debug.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.debug.core; singleton:=true
-Bundle-Version: 3.17.100.qualifier
+Bundle-Version: 3.18.0.qualifier
Bundle-ClassPath: .
Bundle-Activator: org.eclipse.debug.core.DebugPlugin
Bundle-Vendor: %providerName
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java
index f35c70ed8..0a9b71229 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/DebugPlugin.java
@@ -356,6 +356,21 @@ public class DebugPlugin extends Plugin {
public static final String ATTR_PATH = PI_DEBUG_CORE + ".ATTR_PATH"; //$NON-NLS-1$
/**
+ * Launch configuration attribute that designates whether or not the
+ * descendants of the {@link IProcess} associated to a launch of this
+ * configuration should be terminated if the main-process is terminated. The
+ * descendants (also called child- or sub-processes) of a operating system
+ * process are the processes started by that process.
+ *
+ * Value is a string representing a boolean - <code>true</code> or
+ * <code>false</code>. When unspecified, the default value is considered
+ * <code>true</code>.
+ *
+ * @since 3.18
+ */
+ public static final String ATTR_TERMINATE_DESCENDANTS = PI_DEBUG_CORE + ".TERMINATE_DESCENDANTS"; //$NON-NLS-1$
+
+ /**
* The singleton debug plug-in instance.
*/
private static DebugPlugin fgDebugPlugin= null;
diff --git a/org.eclipse.debug.core/core/org/eclipse/debug/core/model/RuntimeProcess.java b/org.eclipse.debug.core/core/org/eclipse/debug/core/model/RuntimeProcess.java
index bef44820a..98122a8d6 100644
--- a/org.eclipse.debug.core/core/org/eclipse/debug/core/model/RuntimeProcess.java
+++ b/org.eclipse.debug.core/core/org/eclipse/debug/core/model/RuntimeProcess.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2020 IBM Corporation and others.
+ * Copyright (c) 2000, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.core.runtime.Status;
@@ -102,6 +103,11 @@ public class RuntimeProcess extends PlatformObject implements IProcess {
private boolean fCaptureOutput = true;
/**
+ * Whether the descendants of this process should be terminated too
+ */
+ private boolean fTerminateDescendants = true;
+
+ /**
* Constructs a RuntimeProcess on the given system process
* with the given name, adding this process to the given
* launch.
@@ -127,6 +133,15 @@ public class RuntimeProcess extends PlatformObject implements IProcess {
String captureOutput = launch.getAttribute(DebugPlugin.ATTR_CAPTURE_OUTPUT);
fCaptureOutput = !("false".equals(captureOutput)); //$NON-NLS-1$
+ try {
+ ILaunchConfiguration launchConfiguration = launch.getLaunchConfiguration();
+ if (launchConfiguration != null) {
+ fTerminateDescendants = launchConfiguration.getAttribute(DebugPlugin.ATTR_TERMINATE_DESCENDANTS, true);
+ }
+ } catch (CoreException e) {
+ DebugPlugin.log(e);
+ }
+
fStreamsProxy = createStreamsProxy();
fMonitor = new ProcessMonitorThread();
fMonitor.start();
@@ -209,12 +224,13 @@ public class RuntimeProcess extends PlatformObject implements IProcess {
return;
}
- List<ProcessHandle> descendants; // only a snapshot!
- try {
- descendants = process.descendants().collect(Collectors.toList());
- } catch (UnsupportedOperationException e) {
- // JVM may not support toHandle() -> assume no descendants
- descendants = Collections.emptyList();
+ List<ProcessHandle> descendants = Collections.emptyList();
+ if (fTerminateDescendants) {
+ try { // List of descendants of process is only a snapshot!
+ descendants = process.descendants().collect(Collectors.toList());
+ } catch (UnsupportedOperationException e) {
+ // JVM may not support toHandle() -> assume no descendants
+ }
}
process.destroy();
diff --git a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/RuntimeProcessTests.java b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/RuntimeProcessTests.java
index 79e4b68cd..bbcca06ea 100644
--- a/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/RuntimeProcessTests.java
+++ b/org.eclipse.debug.tests/src/org/eclipse/debug/tests/console/RuntimeProcessTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2020 Paul Pazderski and others.
+ * Copyright (c) 2020, 2021 Paul Pazderski and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -22,6 +22,7 @@ import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.debug.core.DebugEvent;
@@ -32,7 +33,6 @@ import org.eclipse.debug.internal.core.DebugCoreMessages;
import org.eclipse.debug.tests.AbstractDebugTest;
import org.eclipse.debug.tests.TestUtil;
import org.junit.Test;
-import org.junit.function.ThrowingRunnable;
public class RuntimeProcessTests extends AbstractDebugTest {
@@ -129,6 +129,31 @@ public class RuntimeProcessTests extends AbstractDebugTest {
}
/**
+ * Test {@link RuntimeProcess} terminating the wrapped process while not
+ * terminating its descendants.
+ */
+ @Test
+ public void testTerminateProcessWithoutTerminatingDescendents() throws Exception {
+
+ MockProcess childProcess = new MockProcess(MockProcess.RUN_FOREVER);
+
+ MockProcess mockProcess = new MockProcess(MockProcess.RUN_FOREVER);
+ mockProcess.setHandle(new MockProcessHandle(mockProcess, List.of(childProcess)));
+
+ RuntimeProcess runtimeProcess = mockProcess.toRuntimeProcess("MockProcess", Map.of(DebugPlugin.ATTR_TERMINATE_DESCENDANTS, false));
+
+ assertTrue("RuntimeProcess already terminated.", childProcess.isAlive());
+ assertFalse("RuntimeProcess already terminated.", runtimeProcess.isTerminated());
+
+ runtimeProcess.terminate();
+
+ assertFalse("RuntimeProcess failed to terminate wrapped process.", mockProcess.isAlive());
+ assertTrue("RuntimeProcess terminated child of wrapped process, unlike configured.", childProcess.isAlive());
+
+ TestUtil.waitWhile(p -> !p.isTerminated(), runtimeProcess, 1000, p -> "RuntimePocess not terminated.");
+ }
+
+ /**
* Test {@link RuntimeProcess} terminating the wrapped process which does
* not support {@link Process#toHandle()}.
*/
@@ -140,7 +165,7 @@ public class RuntimeProcessTests extends AbstractDebugTest {
// implementation is called which throws an
// UnsupportedOperationException
mockProcess.setHandle(null);
- assertThrows(UnsupportedOperationException.class, () -> mockProcess.toHandle());
+ assertThrows(UnsupportedOperationException.class, mockProcess::toHandle);
RuntimeProcess runtimeProcess = mockProcess.toRuntimeProcess();
runtimeProcess.terminate(); // must not throw, even toHandle() does
@@ -158,9 +183,8 @@ public class RuntimeProcessTests extends AbstractDebugTest {
mockProcess.setTerminationDelay(6000);
RuntimeProcess runtimeProcess = mockProcess.toRuntimeProcess();
- ThrowingRunnable termianteProcess = () -> runtimeProcess.terminate();
- DebugException timeoutException = assertThrows(DebugException.class, termianteProcess);
+ DebugException timeoutException = assertThrows(DebugException.class, runtimeProcess::terminate);
assertThat(timeoutException.getMessage(), is(DebugCoreMessages.RuntimeProcess_terminate_failed));
}
@@ -178,9 +202,8 @@ public class RuntimeProcessTests extends AbstractDebugTest {
mockProcess.setHandle(new MockProcessHandle(mockProcess, List.of(childProcess)));
RuntimeProcess runtimeProcess = mockProcess.toRuntimeProcess();
- ThrowingRunnable termianteProcess = () -> runtimeProcess.terminate();
- DebugException timeoutException = assertThrows(DebugException.class, termianteProcess);
+ DebugException timeoutException = assertThrows(DebugException.class, runtimeProcess::terminate);
assertThat(timeoutException.getMessage(), is(DebugCoreMessages.RuntimeProcess_terminate_failed));
}
}
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java
index d2ed415e3..84a080257 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.java
@@ -63,6 +63,7 @@ public class LaunchConfigurationsMessages extends NLS {
public static String CommonTab_AttributeLabel_AppendToFile;
public static String CommonTab_AttributeLabel_LaunchInBackground;
public static String CommonTab_AttributeLabel_FavoriteGroups;
+ public static String CommonTab_AttributeLabel_TerminateDescendants;
public static String CompileErrorProjectPromptStatusHandler_0;
public static String CompileErrorProjectPromptStatusHandler_1;
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties
index a26a4d1cc..5a9456a68 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/launchConfigurations/LaunchConfigurationsMessages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2000, 2019 IBM Corporation and others.
+# Copyright (c) 2000, 2021 IBM Corporation and others.
#
# This program and the accompanying materials
# are made available under the terms of the Eclipse Public License 2.0
@@ -55,6 +55,7 @@ CommonTab_AttributeLabel_CaptureInFile=Capture in file
CommonTab_AttributeLabel_AppendToFile=Append to file
CommonTab_AttributeLabel_LaunchInBackground=Launch in background
CommonTab_AttributeLabel_FavoriteGroups=Favorite groups
+CommonTab_AttributeLabel_TerminateDescendants=&Terminate child-processes if terminating the launched process
CompileErrorPromptStatusHandler_0=Errors in Workspace
CompileErrorPromptStatusHandler_1=Errors exist in a required project. Continue launch?
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/CommonTab.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/CommonTab.java
index 5e34555e7..405867a5e 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/CommonTab.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/ui/CommonTab.java
@@ -124,6 +124,7 @@ public class CommonTab extends AbstractLaunchConfigurationTab {
private Text fSharedLocationText;
private Button fSharedLocationButton;
private Button fLaunchInBackgroundButton;
+ private Button fTerminateDescendantsButton;
private Button fDefaultEncodingButton;
private Button fAltEncodingButton;
private Combo fEncodingCombo;
@@ -173,6 +174,7 @@ public class CommonTab extends AbstractLaunchConfigurationTab {
createEncodingComponent(comp);
createOutputCaptureComponent(comp);
createLaunchInBackgroundComponent(comp);
+ createTerminateDescendantsButtonComponent(comp);
}
/**
@@ -501,6 +503,22 @@ public class CommonTab extends AbstractLaunchConfigurationTab {
}
/**
+ * Creates the controls needed to edit the terminate descendants attribute of an
+ * external tool
+ *
+ * @param parent the composite to create the controls in
+ */
+ private void createTerminateDescendantsButtonComponent(Composite parent) {
+ fTerminateDescendantsButton = createCheckButton(parent,
+ LaunchConfigurationsMessages.CommonTab_AttributeLabel_TerminateDescendants);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL);
+ data.horizontalSpan = 2;
+ fTerminateDescendantsButton.setLayoutData(data);
+ fTerminateDescendantsButton.setFont(parent.getFont());
+ fTerminateDescendantsButton.addSelectionListener(widgetSelectedAdapter(e -> updateLaunchConfigurationDialog()));
+ }
+
+ /**
* handles the shared radio button being selected
*/
private void handleSharedRadioButtonSelected() {
@@ -621,6 +639,9 @@ public class CommonTab extends AbstractLaunchConfigurationTab {
updateLaunchInBackground(configuration);
updateEncoding(configuration);
updateConsoleOutput(configuration);
+
+ boolean terminateDescendants = getAttribute(configuration, DebugPlugin.ATTR_TERMINATE_DESCENDANTS, true);
+ fTerminateDescendantsButton.setSelection(terminateDescendants);
}
/**
@@ -934,7 +955,13 @@ public class CommonTab extends AbstractLaunchConfigurationTab {
public void performApply(ILaunchConfigurationWorkingCopy configuration) {
updateConfigFromLocalShared(configuration);
updateConfigFromFavorites(configuration);
- setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, configuration, fLaunchInBackgroundButton.getSelection(), true);
+
+ boolean launchInBackground = fLaunchInBackgroundButton.getSelection();
+ setAttribute(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, configuration, launchInBackground, true);
+
+ boolean terminateDescendants = fTerminateDescendantsButton.getSelection();
+ setAttribute(DebugPlugin.ATTR_TERMINATE_DESCENDANTS, configuration, terminateDescendants, true);
+
String encoding = null;
if(fAltEncodingButton.getSelection()) {
encoding = fEncodingCombo.getText().trim();
@@ -1022,6 +1049,7 @@ public class CommonTab extends AbstractLaunchConfigurationTab {
getAttributesLabelsForPrototype().put(IDebugUIConstants.ATTR_APPEND_TO_FILE, LaunchConfigurationsMessages.CommonTab_AttributeLabel_AppendToFile);
getAttributesLabelsForPrototype().put(IDebugUIConstants.ATTR_LAUNCH_IN_BACKGROUND, LaunchConfigurationsMessages.CommonTab_AttributeLabel_LaunchInBackground);
getAttributesLabelsForPrototype().put(IDebugUIConstants.ATTR_FAVORITE_GROUPS, LaunchConfigurationsMessages.CommonTab_AttributeLabel_FavoriteGroups);
+ getAttributesLabelsForPrototype().put(DebugPlugin.ATTR_TERMINATE_DESCENDANTS, LaunchConfigurationsMessages.CommonTab_AttributeLabel_TerminateDescendants);
}
/**

Back to the top