diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/FinalLaunchSequence.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/FinalLaunchSequence.java index 2950525e72c..6fddd36bd65 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/FinalLaunchSequence.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/launching/FinalLaunchSequence.java @@ -15,9 +15,7 @@ import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; -import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.IProcessInfo; -import org.eclipse.cdt.core.IProcessList; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants; import org.eclipse.cdt.debug.internal.core.sourcelookup.CSourceLookupDirector; @@ -33,12 +31,14 @@ import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.variables.VariablesPlugin; +import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.DsfExecutor; import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.Sequence; import org.eclipse.dd.dsf.datamodel.IDMContext; import org.eclipse.dd.dsf.debug.service.IProcesses.IProcessDMContext; +import org.eclipse.dd.dsf.debug.service.IProcesses.IThreadDMData; import org.eclipse.dd.dsf.service.DsfServicesTracker; import org.eclipse.dd.gdb.internal.GdbPlugin; import org.eclipse.dd.gdb.internal.provisional.IGDBLaunchConfigurationConstants; @@ -47,7 +47,7 @@ import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.SessionType; import org.eclipse.dd.mi.service.CSourceLookup; import org.eclipse.dd.mi.service.MIBreakpointsManager; -import org.eclipse.dd.mi.service.command.commands.CLIMonitorListProcesses; +import org.eclipse.dd.mi.service.ProcessInfo; import org.eclipse.dd.mi.service.command.commands.CLISource; import org.eclipse.dd.mi.service.command.commands.MIEnvironmentCD; import org.eclipse.dd.mi.service.command.commands.MIFileExecAndSymbols; @@ -56,10 +56,8 @@ import org.eclipse.dd.mi.service.command.commands.MIGDBSetAutoSolib; import org.eclipse.dd.mi.service.command.commands.MIGDBSetSolibSearchPath; import org.eclipse.dd.mi.service.command.commands.MIGDBSetSysroot; import org.eclipse.dd.mi.service.command.commands.MITargetSelect; -import org.eclipse.dd.mi.service.command.output.CLIMonitorListProcessesInfo; import org.eclipse.dd.mi.service.command.output.MIInfo; import org.eclipse.debug.core.DebugPlugin; -import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.IStatusHandler; public class FinalLaunchSequence extends Sequence { @@ -361,72 +359,53 @@ public class FinalLaunchSequence extends Sequence { * If attach session, perform the attach. */ new Step() { - private void promptForProcessID(final ILaunchConfiguration config, final DataRequestMonitor rm) { + + // Need a job because prompter.handleStatus will block + class PromptForPidJob extends Job { + + // The list of processes used in the case of an ATTACH session + IProcessInfo[] fProcessList = null; + DataRequestMonitor fRequestMonitor; + + public PromptForPidJob(String name, IProcessInfo[] procs, DataRequestMonitor rm) { + super(name); + fProcessList = procs; + fRequestMonitor = rm; + } + + @Override + protected IStatus run(IProgressMonitor monitor) { IStatus promptStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200/*STATUS_HANDLER_PROMPT*/, "", null); //$NON-NLS-1$//$NON-NLS-2$ final IStatus processPromptStatus = new Status(IStatus.INFO, "org.eclipse.dd.gdb.ui", 100, "", null); //$NON-NLS-1$//$NON-NLS-2$ final IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(promptStatus); - final Status noPidStatus = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, + final Status NO_PID_STATUS = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, LaunchMessages.getString("LocalAttachLaunchDelegate.No_Process_ID_selected"), //$NON-NLS-1$ null); if (prompter == null) { - rm.setStatus(noPidStatus); - rm.done(); - return; - } - - // Need a job because prompter.handleStatus will block - final Job promptForPid = new Job("Prompt for Process") { //$NON-NLS-1$ - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - Object result = prompter.handleStatus(processPromptStatus, fProcessList); - if (result instanceof Integer) { - rm.setData((Integer)result); - } else { - rm.setStatus(noPidStatus); - } - } catch (CoreException e) { - rm.setStatus(noPidStatus); - } - rm.done(); + fRequestMonitor.setStatus(NO_PID_STATUS); + fRequestMonitor.done(); + return Status.OK_STATUS; + } - return Status.OK_STATUS; + try { + Object result = prompter.handleStatus(processPromptStatus, fProcessList); + if (result instanceof Integer) { + fRequestMonitor.setData(fProcService.createProcessContext(Integer.toString((Integer)result))); + } else { + fRequestMonitor.setStatus(NO_PID_STATUS); } - }; - - if (fSessionType == SessionType.LOCAL) { - try { - IProcessList list = CCorePlugin.getDefault().getProcessList(); - if (list != null) fProcessList = list.getProcessList(); - } catch (CoreException e) { - } finally { - // If the list is null, the prompter will deal with it - promptForPid.schedule(); - } - } else { - fCommandControl.queueCommand( - new CLIMonitorListProcesses(fCommandControl.getControlDMContext()), - new DataRequestMonitor(getExecutor(), rm) { - @Override - protected void handleCompleted() { - if (isSuccess()) { - fProcessList = getData().getProcessList(); - } else { - // The monitor list command is not supported. - // Just set the list to empty and let the user - // put in the pid directly. - fProcessList = new IProcessInfo[0]; - } - - promptForPid.schedule(); - } - }); + } catch (CoreException e) { + fRequestMonitor.setStatus(NO_PID_STATUS); } - } + fRequestMonitor.done(); + return Status.OK_STATUS; + } + }; + @Override public void execute(final RequestMonitor requestMonitor) { if (fAttach) { @@ -440,25 +419,61 @@ public class FinalLaunchSequence extends Sequence { } if (pid != -1) { + //FIXME IProcessDMContext procDmc = fProcService.createProcessContext(Integer.toString(pid)); fProcService.attachDebuggerToProcess( procDmc, - new DataRequestMonitor(getExecutor(), requestMonitor)); + new DataRequestMonitor(getExecutor(), requestMonitor)); } else { - promptForProcessID(fLaunch.getLaunchConfiguration(), - new DataRequestMonitor(getExecutor(), requestMonitor) { - @Override - protected void handleSuccess() { - IProcessDMContext procDmc = - fProcService.createProcessContext(Integer.toString(getData())); + fProcService.getRunningProcesses( + fCommandControl.getGDBDMContext(), + new DataRequestMonitor(getExecutor(), requestMonitor) { + @Override + protected void handleSuccess() { + + final List procInfoList = new ArrayList(); + + // For each process, obtain its name + // Once all the names are obtained, prompt the user the pid to use + final CountingRequestMonitor countingRm = + new CountingRequestMonitor(getExecutor(), requestMonitor) { + @Override + protected void handleSuccess() { + new PromptForPidJob( + "Prompt for Process", procInfoList.toArray(new IProcessInfo[0]), //$NON-NLS-1$ + new DataRequestMonitor(getExecutor(), requestMonitor) { + @Override + protected void handleSuccess() { + fProcService.attachDebuggerToProcess( + getData(), + new DataRequestMonitor(getExecutor(), requestMonitor)); + } + }).schedule(); + } + }; - fProcService.attachDebuggerToProcess( - procDmc, - new DataRequestMonitor(getExecutor(), requestMonitor)); - } - }); + countingRm.setDoneCount(getData().length); + + for (IProcessDMContext processCtx : getData()) { + fProcService.getExecutionData( + processCtx, + new DataRequestMonitor (getExecutor(), countingRm) { + @Override + protected void handleSuccess() { + int pid = 0; + try { + pid = Integer.parseInt(getData().getId()); + } catch (NumberFormatException e) { + } + procInfoList.add(new ProcessInfo(pid, getData().getName())); + countingRm.done(); + } + }); + } + } + }); } } else { requestMonitor.done(); @@ -492,10 +507,7 @@ public class FinalLaunchSequence extends Sequence { GDBControl fCommandControl; GDBProcesses fProcService; - - // The list of processes used in the case of an ATTACH session - IProcessInfo[] fProcessList = null; - + public FinalLaunchSequence(DsfExecutor executor, GdbLaunch launch, SessionType sessionType, boolean attach) { super(executor); fLaunch = launch; diff --git a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java index c43965107a1..ccc0f6a3fcf 100644 --- a/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java +++ b/plugins/org.eclipse.dd.gdb/src/org/eclipse/dd/gdb/internal/provisional/service/GDBProcesses.java @@ -10,9 +10,14 @@ *******************************************************************************/ package org.eclipse.dd.gdb.internal.provisional.service; +import java.util.HashMap; import java.util.Hashtable; +import java.util.Map; +import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.IProcessInfo; +import org.eclipse.cdt.core.IProcessList; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; @@ -25,6 +30,7 @@ import org.eclipse.dd.dsf.service.AbstractDsfService; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.gdb.internal.GdbPlugin; import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl; +import org.eclipse.dd.gdb.internal.provisional.service.command.GDBControl.SessionType; import org.eclipse.dd.mi.service.command.commands.CLIAttach; import org.eclipse.dd.mi.service.command.commands.CLIMonitorListProcesses; import org.eclipse.dd.mi.service.command.output.CLIMonitorListProcessesInfo; @@ -126,6 +132,10 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses { } private GDBControl fCommandControl; + + // A map of pid to names. It is filled when we get all the + // processes that are running + private Map fProcessNames = new HashMap(); public GDBProcesses(DsfSession session) { super(session); @@ -231,8 +241,17 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses { public void getExecutionData(IThreadDMContext dmc, DataRequestMonitor rm) { // We must first check for GdbProcessDMC because it is also a GdbThreadDMC if (dmc instanceof GdbProcessDMC) { - rm.setData(new GdbThreadDMData(fCommandControl.getExecutablePath().lastSegment(), - ((GdbProcessDMC)dmc).getId())); + String pidStr = ((GdbProcessDMC)dmc).getId(); + int pid = 0; + try { + pid = Integer.parseInt(pidStr); + } catch (NumberFormatException e) { + } + + String name = fProcessNames.get(pid); + // If we don't find the name in our list, return the default name of our program + if (name == null) name = fCommandControl.getExecutablePath().lastSegment(); + rm.setData(new GdbThreadDMData(name, pidStr)); rm.done(); } else if (dmc instanceof GdbThreadDMC) { rm.setData(new GdbThreadDMData("", ((GdbThreadDMC)dmc).getId())); //$NON-NLS-1$ @@ -317,22 +336,60 @@ public class GDBProcesses extends AbstractDsfService implements IProcesses { rm.done(); } - public void getRunningProcesses(IDMContext dmc, DataRequestMonitor rm) { - // monitor list processes is only for remote session - fCommandControl.queueCommand( - new CLIMonitorListProcesses(dmc), - new DataRequestMonitor(getExecutor(), rm) { - @Override - protected void handleSuccess() { - IProcessInfo[] processes = getData().getProcessList(); - IProcessDMContext[] procDmcs = new GdbProcessDMC[processes.length]; - for (int i=0; i rm) { + if (fCommandControl.getSessionType() == SessionType.LOCAL) { + IProcessList list = null; + try { + list = CCorePlugin.getDefault().getProcessList(); + } catch (CoreException e) { + } + + if (list == null) { + // If the list is null, the prompter will deal with it + fProcessNames.clear(); + rm.setData(null); + } else { + fProcessNames.clear(); + for (IProcessInfo procInfo : list.getProcessList()) { + fProcessNames.put(procInfo.getPid(), procInfo.getName()); + } + rm.setData(makeProcessDMCs(list.getProcessList())); + } + rm.done(); + } else { + // monitor list processes is only for remote session + fCommandControl.queueCommand( + new CLIMonitorListProcesses(dmc), + new DataRequestMonitor(getExecutor(), rm) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + for (IProcessInfo procInfo : getData().getProcessList()) { + fProcessNames.put(procInfo.getPid(), procInfo.getName()); + } + rm.setData(makeProcessDMCs(getData().getProcessList())); + } else { + // The monitor list command is not supported. + // Just return an empty list and let the caller deal with it. + fProcessNames.clear(); + rm.setData(new IProcessDMContext[0]); + } + rm.done(); } - } - }); + + }); + } } + private IProcessDMContext[] makeProcessDMCs(IProcessInfo[] processes) { + IProcessDMContext[] procDmcs = new GdbProcessDMC[processes.length]; + for (int i=0; i rm) { rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$ diff --git a/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/ProcessInfo.java b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/ProcessInfo.java new file mode 100644 index 00000000000..d9d48ccd157 --- /dev/null +++ b/plugins/org.eclipse.dd.mi/src/org/eclipse/dd/mi/service/ProcessInfo.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) 2008 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 + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.dd.mi.service; + +import org.eclipse.cdt.core.IProcessInfo; +import org.eclipse.dd.dsf.concurrent.Immutable; + +@Immutable +public class ProcessInfo implements IProcessInfo, Comparable { + private final int pid; + private final String name; + + public ProcessInfo(String pidString, String name) { + int tmpPid = 0; + try { + tmpPid = Integer.parseInt(pidString); + } catch (NumberFormatException e) { + } + this.pid = tmpPid; + this.name = name; + } + + public ProcessInfo(int pid, String name) { + this.pid = pid; + this.name = name; + } + + /** + * @see org.eclipse.cdt.core.IProcessInfo#getName() + */ + public String getName() { + return name; + } + + /** + * @see org.eclipse.cdt.core.IProcessInfo#getPid() + */ + public int getPid() { + return pid; + } + + public int compareTo(ProcessInfo other) { + int nameCompare = getName().compareTo(other.getName()); + if (nameCompare != 0) return nameCompare; + else return (getPid() < other.getPid()) ? -1 : 1; + } +} \ No newline at end of file