1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 09:25:31 +02:00

Bug 237306: Support for Multi-Process debugging. Add a "New..." button to the "Attach dialog" to allow creating a new process from a running session.

This commit is contained in:
Marc Khouzam 2011-03-10 21:28:59 +00:00
parent 892202e967
commit 87515ad676
4 changed files with 118 additions and 22 deletions

View file

@ -11,6 +11,7 @@
package org.eclipse.cdt.dsf.gdb.internal.ui.actions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RejectedExecutionException;
@ -19,6 +20,7 @@ import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
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.Query;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
@ -29,6 +31,7 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.internal.ui.launching.ProcessPrompter.PrompterInfo;
import org.eclipse.cdt.dsf.gdb.launching.IProcessExtendedInfo;
import org.eclipse.cdt.dsf.gdb.launching.LaunchMessages;
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses.IGdbThreadDMData;
@ -85,14 +88,16 @@ public class GdbConnectCommand implements IConnect {
}
// Need a job because prompter.handleStatus will block
class PromptForPidJob extends Job {
protected class PromptForPidJob extends Job {
// The list of processes used in the case of an ATTACH session
IProcessExtendedInfo[] fProcessList = null;
DataRequestMonitor<Integer> fRequestMonitor;
DataRequestMonitor<Object> fRequestMonitor;
boolean fNewProcessSupported;
public PromptForPidJob(String name, IProcessExtendedInfo[] procs, DataRequestMonitor<Integer> rm) {
public PromptForPidJob(String name, boolean newProcessSupported, IProcessExtendedInfo[] procs, DataRequestMonitor<Object> rm) {
super(name);
fNewProcessSupported = newProcessSupported;
fProcessList = procs;
fRequestMonitor = rm;
}
@ -115,10 +120,11 @@ public class GdbConnectCommand implements IConnect {
}
try {
Object result = prompter.handleStatus(processPromptStatus, fProcessList);
if (result instanceof Integer) {
fRequestMonitor.setData((Integer)result);
} else {
PrompterInfo info = new PrompterInfo(fNewProcessSupported, fProcessList);
Object result = prompter.handleStatus(processPromptStatus, info);
if (result instanceof Integer || result instanceof String) {
fRequestMonitor.setData(result);
} else {
fRequestMonitor.setStatus(NO_PID_STATUS);
}
} catch (CoreException e) {
@ -151,7 +157,12 @@ public class GdbConnectCommand implements IConnect {
ICommandControlService commandControl = fTracker.getService(ICommandControlService.class);
if (procService != null && commandControl != null) {
final ICommandControlDMContext controlCtx = commandControl.getContext();
final ICommandControlDMContext controlCtx = commandControl.getContext();
procService.isDebugNewProcessSupported(controlCtx, new DataRequestMonitor<Boolean>(fExecutor, null) {
@Override
protected void handleCompleted() {
final boolean newProcessSupported = isSuccess() && getData();
procService.getRunningProcesses(
controlCtx,
new DataRequestMonitor<IProcessDMContext[]>(fExecutor, rm) {
@ -165,16 +176,29 @@ public class GdbConnectCommand implements IConnect {
@Override
protected void handleSuccess() {
new PromptForPidJob(
"Prompt for Process", procInfoList.toArray(new IProcessExtendedInfo[0]), //$NON-NLS-1$
new DataRequestMonitor<Integer>(fExecutor, rm) {
"Prompt for Process", newProcessSupported, procInfoList.toArray(new IProcessExtendedInfo[0]), //$NON-NLS-1$
new DataRequestMonitor<Object>(fExecutor, rm) {
@Override
protected void handleSuccess() {
// New cycle, look for service again
final IMIProcesses procService = fTracker.getService(IMIProcesses.class);
if (procService != null) {
IProcessDMContext procDmc = procService.createProcessContext(controlCtx,
Integer.toString(getData()));
procService.attachDebuggerToProcess(procDmc, new DataRequestMonitor<IDMContext>(fExecutor, rm));
Object data = getData();
if (data instanceof String) {
// User wants to start a new process
String binaryPath = (String)data;
procService.debugNewProcess(
controlCtx, binaryPath,
// khouzam, maybe we should at least pass stopOnMain?
new HashMap<String, Object>(), new DataRequestMonitor<IDMContext>(fExecutor, rm));
} else if (data instanceof Integer) {
IProcessDMContext procDmc = procService.createProcessContext(controlCtx,
Integer.toString((Integer)getData()));
procService.attachDebuggerToProcess(procDmc, new DataRequestMonitor<IDMContext>(fExecutor, rm));
} else {
rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Invalid return type for process prompter", null)); //$NON-NLS-1$
rm.done();
}
}
}
}).schedule();
@ -246,6 +270,8 @@ public class GdbConnectCommand implements IConnect {
}
}
});
}
});
} else {
rm.done();
}

View file

@ -222,3 +222,8 @@ LocalCDILaunchDelegate.7=Core file does not exist or is not readable.
LocalCDILaunchDelegate.8=Error starting process.
LocalCDILaunchDelegate.9=Eclipse runtime does not support working directory.
LocalCDILaunchDelegate.10=Failed to set program arguments, environment or working directory.
ProcessPrompter.Core=core
ProcessPrompter.Cores=cores
ProcessPrompterDialog.New=New...

View file

@ -28,17 +28,26 @@ 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.TwoPaneElementSelector;
public class ProcessPrompter implements IStatusHandler {
public static class PrompterInfo {
public boolean supportsNewProcess;
public IProcessExtendedInfo[] processList;
public PrompterInfo(boolean supportsNew, IProcessExtendedInfo[] list) {
supportsNewProcess = supportsNew;
processList = list;
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.debug.core.IStatusHandler#handleStatus(org.eclipse.core.runtime.IStatus,
* java.lang.Object)
*/
public Object handleStatus(IStatus status, Object processList) throws CoreException {
public Object handleStatus(IStatus status, Object info) throws CoreException {
Shell shell = GdbUIPlugin.getShell();
if (shell == null) {
IStatus error = new Status(IStatus.ERROR, GdbUIPlugin.getUniqueIdentifier(),
@ -47,7 +56,8 @@ public class ProcessPrompter implements IStatusHandler {
throw new CoreException(error);
}
IProcessExtendedInfo[] plist = (IProcessExtendedInfo[])processList;
PrompterInfo prompterInfo = (PrompterInfo) info;
IProcessExtendedInfo[] plist = prompterInfo.processList;
if (plist == null) {
MessageDialog.openError(
shell,
@ -91,11 +101,14 @@ public class ProcessPrompter implements IStatusHandler {
String[] cores = info.getCores();
if (cores != null && cores.length > 0) {
String coreStr;
if (cores.length == 1) {
text.append(" [core: ");
coreStr = LaunchUIMessages.getString("ProcessPrompter.Core"); //$NON-NLS-1$
} else {
text.append(" [cores: ");
coreStr = LaunchUIMessages.getString("ProcessPrompter.Cores"); //$NON-NLS-1$
}
text.append(" [" + coreStr + ": "); //$NON-NLS-1$//$NON-NLS-2$
for (String core : cores) {
text.append(core + ", "); //$NON-NLS-1$
}
@ -133,15 +146,21 @@ public class ProcessPrompter implements IStatusHandler {
};
// Display the list of processes and have the user choose
TwoPaneElementSelector dialog = new TwoPaneElementSelector(shell, provider, qprovider);
ProcessPrompterDialog dialog = new ProcessPrompterDialog(shell, provider, qprovider, prompterInfo.supportsNewProcess);
dialog.setTitle(LaunchMessages.getString("LocalAttachLaunchDelegate.Select_Process")); //$NON-NLS-1$
dialog.setMessage(LaunchMessages.getString("LocalAttachLaunchDelegate.Select_Process_to_attach_debugger_to")); //$NON-NLS-1$
dialog.setElements(plist);
if (dialog.open() == Window.OK) {
IProcessExtendedInfo info = (IProcessExtendedInfo)dialog.getFirstResult();
if (info != null) {
return new Integer(info.getPid());
// First check if the user pressed the New button
String binaryPath = dialog.getBinaryPath();
if (binaryPath != null) {
return binaryPath;
}
IProcessExtendedInfo processInfo = (IProcessExtendedInfo)dialog.getFirstResult();
if (processInfo != null) {
return new Integer(processInfo.getPid());
}
}
}

View file

@ -0,0 +1,46 @@
package org.eclipse.cdt.dsf.gdb.internal.ui.launching;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.TwoPaneElementSelector;
public class ProcessPrompterDialog extends TwoPaneElementSelector {
private static final int NEW_BUTTON_ID = 9876;
private String fBinaryPath;
private boolean fSupportsNewProcess;
public ProcessPrompterDialog(Shell parent, ILabelProvider elementRenderer,
ILabelProvider qualifierRenderer, boolean supportsNewProcess) {
super(parent, elementRenderer, qualifierRenderer);
fSupportsNewProcess = supportsNewProcess;
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
Button newButton = createButton(
parent, NEW_BUTTON_ID, LaunchUIMessages.getString("ProcessPrompterDialog.New"), false); //$NON-NLS-1$
newButton.setEnabled(fSupportsNewProcess);
super.createButtonsForButtonBar(parent);
}
@Override
protected void buttonPressed(int buttonId) {
if (buttonId == NEW_BUTTON_ID) {
FileDialog fd = new FileDialog(getShell(), SWT.SAVE);
fBinaryPath = fd.open();
setReturnCode(OK);
close();
}
super.buttonPressed(buttonId);
}
public String getBinaryPath() {
return fBinaryPath;
}
}