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:
parent
892202e967
commit
87515ad676
4 changed files with 118 additions and 22 deletions
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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...
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue