Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeodor Madan2016-02-09 20:47:35 +0000
committerGerrit Code Review @ Eclipse.org2016-03-03 14:51:24 +0000
commitf29de7ceddd61bb6ce4ed9854f947d682bb02cc1 (patch)
treea93d334b44ccb0f4407e8e06ef68c540bb8dfcb4
parent70fe6cbbde25c54cdad80e1f1f6c98489fc73b72 (diff)
downloadorg.eclipse.cdt-f29de7ceddd61bb6ce4ed9854f947d682bb02cc1.tar.gz
org.eclipse.cdt-f29de7ceddd61bb6ce4ed9854f947d682bb02cc1.tar.xz
org.eclipse.cdt-f29de7ceddd61bb6ce4ed9854f947d682bb02cc1.zip
Bug 487682 - refuse process selection for already connected process
- Extend query for already connected process to all sessions for local session types Change-Id: I36591ff96d28977b4670700a2a2eb92c34945c7a Signed-off-by: Teodor Madan <teodor.madan@nxp.com>
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java155
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties6
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java29
-rw-r--r--dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java31
4 files changed, 182 insertions, 39 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java
index ac2e2b94558..acb95c231e8 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbConnectCommand.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2015 Ericsson and others.
+ * Copyright (c) 2008, 2016 Ericsson and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -14,10 +14,12 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
@@ -28,8 +30,11 @@ import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
+import org.eclipse.cdt.dsf.concurrent.ImmediateInDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
@@ -50,6 +55,7 @@ import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses.IGdbThreadDMData;
+import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
import org.eclipse.cdt.dsf.gdb.service.SessionType;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
@@ -149,13 +155,15 @@ public class GdbConnectCommand extends RefreshableDebugCommand implements IConne
DataRequestMonitor<Object> fRequestMonitor;
boolean fNewProcessSupported;
boolean fRemote;
+ private List<String> fDebuggedProcesses;
- public PromptForPidJob(String name, boolean newProcessSupported, boolean remote, IProcessExtendedInfo[] procs, DataRequestMonitor<Object> rm) {
+ public PromptForPidJob(String name, boolean newProcessSupported, boolean remote, IProcessExtendedInfo[] procs, List<String> debuggedProcesses, DataRequestMonitor<Object> rm) {
super(name);
fNewProcessSupported = newProcessSupported;
fRemote = remote;
fProcessList = procs;
fRequestMonitor = rm;
+ fDebuggedProcesses = debuggedProcesses;
}
@Override
@@ -165,7 +173,7 @@ public class GdbConnectCommand extends RefreshableDebugCommand implements IConne
null);
try {
- PrompterInfo info = new PrompterInfo(fNewProcessSupported, fRemote, fProcessList);
+ PrompterInfo info = new PrompterInfo(fNewProcessSupported, fRemote, fProcessList, fDebuggedProcesses);
Object result = new ProcessPrompter().handleStatus(null, info);
if (result == null) {
fRequestMonitor.cancel();
@@ -278,12 +286,87 @@ public class GdbConnectCommand extends RefreshableDebugCommand implements IConne
// Nothing to do, just ignore the command since the user
// cancelled it.
} catch (RejectedExecutionException e) {
- // Can be thrown if the session is shutdown
+ // Can be thrown if the session is shutdown
} finally {
updateEnablement();
}
}
-
+
+ /**
+ * Get already debugged processes from all compatible sessions.
+ * "compatible" in current implementation means all sessions on local machine.
+ *
+ * @param currentCtx current session context
+ * @param allSessions true if all session to be queried, false to return result only for current execution session context
+ * @param drm where result to be returned
+ */
+ private void getAllDebuggedProcesses(final IDMContext currentCtx, boolean allSessions, final DataRequestMonitor<List<String>> drm) {
+ SessionType sessionType = fTracker.getService(IGDBBackend.class).getSessionType();
+
+ final List<String> result = new LinkedList<>();
+ final List<DsfSession> sessions = new LinkedList<>();
+ // Only for local session types search in all debug sessions
+ if (allSessions && sessionType == SessionType.LOCAL) {
+ sessions.addAll(Arrays.asList(DsfSession.getActiveSessions()));
+ } else {
+ // For remote session just query current context.
+ //
+ // cannot reliably match two remote debug session that are connected to same target machine.
+ // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=486408#c7
+
+ sessions.add(DsfSession.getSession(currentCtx.getSessionId()));
+ }
+
+ // Query each sessions for existing processes in a sequential fashion.
+ // We must do this as each session will require different executor.
+ final class ProcessRequestMonitor extends DataRequestMonitor<IDMContext[]> {
+ public ProcessRequestMonitor(Executor executor) { super(executor, null);}
+ public ProcessRequestMonitor(DsfExecutor executor) {
+ super(new ImmediateInDsfExecutor(executor), null);
+ }
+ @Override
+ protected void handleCompleted() {
+ // if succeeded and has data, add process ids to result,
+ // otherwise proceed to next debug session (aka DsfSession)
+ if (isSuccess() && getData() != null) {
+ for (IDMContext dmc : getData()) {
+ IMIProcessDMContext procDmc = DMContexts.getAncestorOfType(dmc,
+ IMIProcessDMContext.class);
+ if (procDmc != null) {
+ result.add(procDmc.getProcId());
+ }
+ }
+ }
+ if (!sessions.isEmpty()) {
+ final DsfSession nextSession = sessions.remove(0);
+ final boolean sameSession = currentCtx.getSessionId().equals(nextSession.getId());
+ nextSession.getExecutor().execute(new DsfRunnable() {
+ @Override
+ public void run() {
+ DsfServicesTracker nextTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), nextSession.getId());
+ IGDBBackend nextSessionBackend = nextTracker.getService(IGDBBackend.class);
+ if (sameSession || nextSessionBackend.getSessionType() == SessionType.LOCAL) {
+ ICommandControlService nextCommandControl = nextTracker.getService(ICommandControlService.class);
+ IProcesses nextProcService = nextTracker.getService(IProcesses.class);
+ nextProcService.getProcessesBeingDebugged(
+ nextCommandControl.getContext(), new ProcessRequestMonitor(nextSession.getExecutor()));
+ } else {
+ // proceed to next session context query passing an error (that will be ignored)
+ new ProcessRequestMonitor(nextSession.getExecutor()).done(
+ new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED, "Only local session", null)); //$NON-NLS-1$
+ }
+ nextTracker.dispose();
+ }
+ });
+ } else {
+ // done with querying all session. Copy the result
+ drm.done(result);
+ }
+ }
+ };
+ // Trigger the first query
+ new ProcessRequestMonitor(ImmediateExecutor.getInstance()).done();
+ }
/*
* This method should not be called from the UI thread.
* (non-Javadoc)
@@ -291,7 +374,7 @@ public class GdbConnectCommand extends RefreshableDebugCommand implements IConne
*/
@Override
public void connect(final RequestMonitor rm)
- {
+ {
fExecutor.execute(new DsfRunnable() {
@Override
public void run() {
@@ -318,35 +401,43 @@ public class GdbConnectCommand extends RefreshableDebugCommand implements IConne
final List<IProcessExtendedInfo> procInfoList = new ArrayList<IProcessExtendedInfo>();
- final CountingRequestMonitor countingRm =
+ final CountingRequestMonitor countingRm =
new CountingRequestMonitor(fExecutor, rm) {
@Override
protected void handleSuccess() {
- // Prompt the user to choose one or more processes, or to start a new one
- new PromptForPidJob(
- LaunchUIMessages.getString("ProcessPrompter.PromptJob"), //$NON-NLS-1$
- newProcessSupported,
- remote,
- procInfoList.toArray(new IProcessExtendedInfo[procInfoList.size()]),
- new DataRequestMonitor<Object>(fExecutor, rm) {
- @Override
- protected void handleCancel() {
- rm.cancel();
- rm.done();
- }
- @Override
- protected void handleSuccess() {
- Object data = getData();
- if (data instanceof NewExecutableInfo) {
- // User wants to start a new process
- startNewProcess(controlCtx, (NewExecutableInfo)data, rm);
- } else if (data instanceof IProcessExtendedInfo[]) {
- attachToProcesses(controlCtx, (IProcessExtendedInfo[])data, rm);
- } else {
- rm.done(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid return type for process prompter", null)); //$NON-NLS-1$
- }
- }
- }).schedule();
+ getAllDebuggedProcesses(controlCtx, true, new ImmediateDataRequestMonitor<List<String>>(rm) {
+ @Override
+ protected void handleSuccess() {
+ List<String> dbgPids = getData();
+
+ // Prompt the user to choose one or more processes, or to start a new one
+ new PromptForPidJob(
+ LaunchUIMessages.getString("ProcessPrompter.PromptJob"), //$NON-NLS-1$
+ newProcessSupported,
+ remote,
+ procInfoList.toArray(new IProcessExtendedInfo[procInfoList.size()]),
+ dbgPids,
+ new DataRequestMonitor<Object>(fExecutor, rm) {
+ @Override
+ protected void handleCancel() {
+ rm.cancel();
+ rm.done();
+ }
+ @Override
+ protected void handleSuccess() {
+ Object data = getData();
+ if (data instanceof NewExecutableInfo) {
+ // User wants to start a new process
+ startNewProcess(controlCtx, (NewExecutableInfo)data, rm);
+ } else if (data instanceof IProcessExtendedInfo[]) {
+ attachToProcesses(controlCtx, (IProcessExtendedInfo[])data, rm);
+ } else {
+ rm.done(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid return type for process prompter", null)); //$NON-NLS-1$
+ }
+ }
+ }).schedule();
+ }
+ });
}
};
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties
index d2886cc9f45..03cf0d35349 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/LaunchUIMessages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2003, 2015 QNX Software Systems and others.
+# Copyright (c) 2003, 2016 QNX Software Systems and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@@ -235,5 +235,7 @@ LocalCDILaunchDelegate.10=Failed to set program arguments, environment or workin
ProcessPrompter.Core=core
ProcessPrompter.Cores=cores
ProcessPrompter.PromptJob=Prompt for Process
+ProcessPrompter.ErrProcessConected=Process {0} already connected
+
ProcessPrompterDialog.New=New...
-ProcessPrompterDialog.TitlePrefix=Choose binary for process: \ No newline at end of file
+ProcessPrompterDialog.TitlePrefix=Choose binary for process:
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java
index 755ef8b2c3b..f95da0bd985 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2014 QNX Software Systems and others.
+ * Copyright (c) 2008, 2016 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -12,6 +12,8 @@
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
+import java.util.List;
+
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.launching.IProcessExtendedInfo;
@@ -29,6 +31,9 @@ import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
+
+import com.ibm.icu.text.MessageFormat;
public class ProcessPrompter implements IStatusHandler {
@@ -36,11 +41,13 @@ public class ProcessPrompter implements IStatusHandler {
public boolean supportsNewProcess;
public boolean remote;
public IProcessExtendedInfo[] processList;
+ public List<String> debuggedProcesses;
- public PrompterInfo(boolean supportsNew, boolean remote, IProcessExtendedInfo[] list) {
+ public PrompterInfo(boolean supportsNew, boolean remote, IProcessExtendedInfo[] list, List<String> debuggedProcs) {
supportsNewProcess = supportsNew;
this.remote = remote;
processList = list;
+ this.debuggedProcesses = debuggedProcs;
}
}
@@ -60,7 +67,7 @@ public class ProcessPrompter implements IStatusHandler {
throw new CoreException(error);
}
- PrompterInfo prompterInfo = (PrompterInfo) info;
+ final PrompterInfo prompterInfo = (PrompterInfo) info;
IProcessExtendedInfo[] plist = prompterInfo.processList;
if (plist == null) {
MessageDialog.openError(
@@ -178,7 +185,21 @@ public class ProcessPrompter implements IStatusHandler {
// Allow for multiple selection
dialog.setMultipleSelection(true);
-
+ dialog.setStatusLineAboveButtons(true);
+
+ dialog.setValidator(new ISelectionStatusValidator() {
+ @Override
+ public IStatus validate(Object[] selection) {
+ for (Object sel : selection) {
+ String pid = Integer.toString(((IProcessExtendedInfo)sel).getPid(), 10);
+ if (prompterInfo.debuggedProcesses.contains(pid)) {
+ return new Status(IStatus.ERROR, GdbUIPlugin.getUniqueIdentifier(),
+ MessageFormat.format(LaunchUIMessages.getString("ProcessPrompter.ErrProcessConected"), pid)); //$NON-NLS-1$
+ }
+ }
+ return new Status(IStatus.OK, GdbUIPlugin.getUniqueIdentifier(), ""); //$NON-NLS-1$
+ }
+ });
dialog.setElements(plist);
if (dialog.open() == Window.OK) {
// First check if the user pressed the New button
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java
index 111827326a4..545ac26f857 100644
--- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java
+++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/launching/ProcessPrompterDialog.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011, 2013 Ericsson and others.
+ * Copyright (c) 2011, 2016 Ericsson and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,8 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
import java.util.Arrays;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.SWT;
@@ -22,6 +24,8 @@ import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.dialogs.TwoPaneElementSelector;
/**
@@ -130,4 +134,29 @@ public class ProcessPrompterDialog extends TwoPaneElementSelector {
public NewExecutableInfo getExecutableInfo() {
return fExecInfo;
}
+
+ /**
+ * Validate only upper selected elements. Lower list is always disabled.
+ *
+ * @see #createLowerList(Composite)
+ */
+ @Override
+ protected boolean validateCurrentSelection() {
+ ISelectionStatusValidator validator = getValidator();
+ Object[] elements = getSelectedElements();
+
+ if (elements.length > 0) {
+ IStatus status;
+ if (validator != null) {
+ status = validator.validate(elements);
+ } else {
+ status = new Status(IStatus.OK, PlatformUI.PLUGIN_ID, IStatus.OK, "", //$NON-NLS-1$
+ null);
+ }
+ updateStatus(status);
+ return status.isOK();
+ }
+
+ return super.validateCurrentSelection();
+ }
}

Back to the top