mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 528145 - Breakpoints are not working with remote attach launch (#336)
Looking at the logs, it seems that the regression is caused at8bec791
where support for multi-process was added. We removed breakpoints tracking support from final launch sequence and moved it to debug new process and attach to process logic but none of these are run for remote attach launch, hence breakpoint tracking is not started for remote attach launch. To fix the problem, IGDBProcesses.attachDebuggerToProcess(..) is updated to handle remote attach launch as well instead of final launch sequence handling it. This commit is created after reverting7bddb5f
and96839a0
which is the older fix done to fix this issue and the other commit was to fix the regression caused by the old fix. The problem with older fix was that for non-stop mode, attach to process was not working for remote launches when there is already a process being debugged. Note that to use this feature, gdbserver should be started with --multi option. * Revert "Bug 580259: Not all remote session have a connected process" This reverts commit96839a029d
. * Revert "Bug 528145 - Attach debugger to a gdbserver remote session" This reverts commit7bddb5f4cb
.
This commit is contained in:
parent
2777c17784
commit
e8f17beeb5
12 changed files with 459 additions and 136 deletions
1
.github/workflows/build-test.yml
vendored
1
.github/workflows/build-test.yml
vendored
|
@ -37,6 +37,7 @@ jobs:
|
|||
run: |
|
||||
export DISPLAY=:99
|
||||
sudo Xvfb -ac :99 -screen 0 1280x1024x24 > /dev/null 2>&1 &
|
||||
echo 0| sudo tee /proc/sys/kernel/yama/ptrace_scope
|
||||
mvn \
|
||||
clean verify -B -V \
|
||||
-Dmaven.test.failure.ignore=true \
|
||||
|
|
|
@ -12,6 +12,10 @@ This is the New & Noteworthy page for CDT 11.2 which is part of Eclipse 2023-06
|
|||
|
||||
Please see [CHANGELOG-API](CHANGELOG-API.md) for details on the breaking API changes in this release as well as future planned API changes.
|
||||
|
||||
## `FinalLaunchSequence.stepRemoteConnection()` and `FinalLaunchSequence.stepAttachRemoteToDebugger()` are deprecated
|
||||
|
||||
The remote connection for attach launch will be moved in the implementation of `IGDBProcesses.attachDebuggerToProcess()`
|
||||
|
||||
# Noteworthy Issues and Pull Requests
|
||||
|
||||
See [Noteworthy issues and PRs](https://github.com/eclipse-cdt/cdt/issues?q=is%3Aclosed+label%3Anoteworthy+milestone%3A11.2.0) for this release in the issue/PR tracker.
|
||||
|
|
|
@ -596,3 +596,11 @@ The class BuiltinDetctionArgsGeneric will be removed. Use the correctly
|
|||
spelled BuiltinDetectionArgsGeneric instead.
|
||||
|
||||
- org.eclipse.cdt.jsoncdb.core.participant.Arglets.BuiltinDetctionArgsGeneric
|
||||
|
||||
## API Removals after June 2025
|
||||
|
||||
### FinalLaunchSequence.stepRemoteConnection() and FinalLaunchSequence.stepAttachRemoteToDebugger() will be removed
|
||||
|
||||
These APIs will be removed and remote connection for attach launch will be moved in the implementation of `IGDBProcesses.attachDebuggerToProcess()`.
|
||||
|
||||
See https://github.com/eclipse-cdt/cdt/pull/336
|
||||
|
|
|
@ -3,7 +3,7 @@ Bundle-ManifestVersion: 2
|
|||
Bundle-Name: %pluginName
|
||||
Bundle-Vendor: %providerName
|
||||
Bundle-SymbolicName: org.eclipse.cdt.dsf.gdb;singleton:=true
|
||||
Bundle-Version: 7.0.0.qualifier
|
||||
Bundle-Version: 7.1.0.qualifier
|
||||
Bundle-Activator: org.eclipse.cdt.dsf.gdb.internal.GdbPlugin
|
||||
Bundle-Localization: plugin
|
||||
Require-Bundle: org.eclipse.core.runtime,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
* Anton Gorenkov - A preference to use RTTI for variable types determination (Bug 377536)
|
||||
* Xavier Raynaud (Kalray) - Avoid duplicating fields in sub-classes (add protected accessors)
|
||||
* Marc Khouzam (Ericsson) - Output the version of GDB at startup (Bug 455408)
|
||||
* Jonathan Tousignant (NordiaSoft) - Remote session breakpoint (Bug 528145)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.launching;
|
||||
|
||||
|
@ -39,7 +38,6 @@ import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
|
|||
import org.eclipse.cdt.dsf.concurrent.RequestMonitorWithProgress;
|
||||
import org.eclipse.cdt.dsf.datamodel.DataModelInitializedEvent;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
|
@ -47,11 +45,11 @@ import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
|||
import org.eclipse.cdt.dsf.gdb.actions.IConnect;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBSourceLookup;
|
||||
import org.eclipse.cdt.dsf.gdb.service.SessionType;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.CSourceLookup;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.MIProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBVersionInfo;
|
||||
|
@ -77,7 +75,7 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
|
||||
private IGDBControl fCommandControl;
|
||||
private IGDBBackend fGDBBackend;
|
||||
private IMIProcesses fProcService;
|
||||
private IGDBProcesses fProcService;
|
||||
private CommandFactory fCommandFactory;
|
||||
|
||||
private DsfServicesTracker fTracker;
|
||||
|
@ -136,13 +134,13 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
//
|
||||
// "stepSetSourceLookupPath", //$NON-NLS-1$
|
||||
|
||||
// For remote-attach launch only
|
||||
// For remote-attach launch only (deprecated, see javadocs)
|
||||
"stepRemoteConnection", //$NON-NLS-1$
|
||||
// For all launches except attach ones
|
||||
"stepNewProcess", //$NON-NLS-1$
|
||||
// For local attach launch only
|
||||
// For all attach launch only
|
||||
"stepAttachToProcess", //$NON-NLS-1$
|
||||
// For remote attach launch only
|
||||
// For remote attach launch only (deprecated, see javadocs)
|
||||
"stepAttachRemoteToDebugger", //$NON-NLS-1$
|
||||
// Global
|
||||
"stepDataModelInitializationComplete", //$NON-NLS-1$
|
||||
|
@ -178,7 +176,7 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
|
||||
fCommandFactory = fCommandControl.getCommandFactory();
|
||||
|
||||
fProcService = fTracker.getService(IMIProcesses.class);
|
||||
fProcService = fTracker.getService(IGDBProcesses.class);
|
||||
if (fProcService == null) {
|
||||
requestMonitor.setStatus(
|
||||
new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, -1, "Cannot obtain process service", null)); //$NON-NLS-1$
|
||||
|
@ -552,13 +550,17 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
rm.done();
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
private static final String INVALID = "invalid"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* If we are dealing with a remote-attach debugging session, connect to the target.
|
||||
* @since 4.0
|
||||
*
|
||||
* When removing, revive/uncomment code in implementations of IGDBProcesses.attachDebuggerToProcess()
|
||||
*/
|
||||
@Execute
|
||||
@Deprecated(forRemoval = true)
|
||||
public void stepRemoteConnection(final RequestMonitor rm) {
|
||||
if (fGDBBackend.getSessionType() == SessionType.REMOTE && fGDBBackend.getIsAttachSession()) {
|
||||
boolean isTcpConnection = CDebugUtils.getAttribute(fAttributes,
|
||||
|
@ -593,19 +595,9 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
@Execute
|
||||
public void stepNewProcess(final RequestMonitor rm) {
|
||||
if (!fGDBBackend.getIsAttachSession()) {
|
||||
boolean noBinarySpecified = CDebugUtils.getAttribute(fAttributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT);
|
||||
|
||||
String binary = null;
|
||||
final IPath execPath = fGDBBackend.getProgramPath();
|
||||
if (!noBinarySpecified && execPath != null && !execPath.isEmpty()) {
|
||||
binary = execPath.toString();
|
||||
}
|
||||
|
||||
// Even if binary is null, we must call this to do all the other steps
|
||||
// necessary to create a process. It is possible that the binary is not needed
|
||||
fProcService.debugNewProcess(fCommandControl.getContext(), binary, fAttributes,
|
||||
fProcService.debugNewProcess(fCommandControl.getContext(), getBinary(), fAttributes,
|
||||
new DataRequestMonitor<IDMContext>(getExecutor(), rm) {
|
||||
@Override
|
||||
protected void handleCancel() {
|
||||
|
@ -623,14 +615,28 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
}
|
||||
|
||||
/**
|
||||
* If we are dealing with an local attach session, perform the attach.
|
||||
* For a remote attach session, we don't attach during the launch; instead
|
||||
* we wait for the user to manually do the attach.
|
||||
* @since 7.1
|
||||
*/
|
||||
protected String getBinary() {
|
||||
boolean noBinarySpecified = CDebugUtils.getAttribute(fAttributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_USE_SOLIB_SYMBOLS_FOR_APP_DEFAULT);
|
||||
|
||||
String binary = null;
|
||||
final IPath execPath = fGDBBackend.getProgramPath();
|
||||
if (!noBinarySpecified && execPath != null && !execPath.isEmpty()) {
|
||||
binary = execPath.toString();
|
||||
}
|
||||
return binary;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are dealing with an attach session, perform the attach.
|
||||
* @since 4.0
|
||||
*/
|
||||
@Execute
|
||||
public void stepAttachToProcess(final RequestMonitor requestMonitor) {
|
||||
if (fGDBBackend.getIsAttachSession() && fGDBBackend.getSessionType() != SessionType.REMOTE) {
|
||||
if (fGDBBackend.getIsAttachSession()) {
|
||||
// Is the process id already stored in the launch?
|
||||
int pid = CDebugUtils.getAttribute(fAttributes, ICDTLaunchConfigurationConstants.ATTR_ATTACH_PROCESS_ID,
|
||||
-1);
|
||||
|
@ -639,6 +645,10 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
fProcService.attachDebuggerToProcess(
|
||||
fProcService.createProcessContext(fCommandControl.getContext(), Integer.toString(pid)),
|
||||
new DataRequestMonitor<IDMContext>(getExecutor(), requestMonitor));
|
||||
} else if (fGDBBackend.getSessionType() == SessionType.REMOTE) {
|
||||
// Inline following and remove requestMonitor.done() once FinalLaunchSequence.stepAttachRemoteToDebugger() is removed
|
||||
// stepAttachRemoteToDebugger(requestMonitor);
|
||||
requestMonitor.done();
|
||||
} else {
|
||||
IConnectHandler connectCommand = (IConnectHandler) fSession.getModelAdapter(IConnectHandler.class);
|
||||
if (connectCommand instanceof IConnect) {
|
||||
|
@ -656,22 +666,19 @@ public class FinalLaunchSequence extends ReflectionSequence {
|
|||
* If we are dealing with an remote attach session, perform the attach to debugger.
|
||||
* Bug 528145
|
||||
* @since 6.6
|
||||
*
|
||||
* When removing, revive/uncomment code in implementations in FinalLaunchSequence.stepAttachToProcess(RequestMonitor)
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
@Execute
|
||||
public void stepAttachRemoteToDebugger(final RequestMonitor requestMonitor) {
|
||||
if (fGDBBackend.getIsAttachSession() && fGDBBackend.getSessionType() == SessionType.REMOTE) {
|
||||
DataRequestMonitor<Boolean> rm = new DataRequestMonitor<>(getExecutor(), null);
|
||||
fProcService.canDetachDebuggerFromProcess(null, rm);
|
||||
|
||||
if (rm.getData()) {
|
||||
IProcessDMContext processContext = fProcService.createProcessContext(fCommandControl.getContext(),
|
||||
MIProcesses.UNKNOWN_PROCESS_ID);
|
||||
fProcService.attachDebuggerToProcess(processContext,
|
||||
new DataRequestMonitor<IDMContext>(getExecutor(), requestMonitor));
|
||||
return;
|
||||
}
|
||||
fProcService.attachDebuggerToProcess(
|
||||
fProcService.createProcessContext(fCommandControl.getContext(), MIProcesses.UNKNOWN_PROCESS_ID),
|
||||
getBinary(), new DataRequestMonitor<IDMContext>(getExecutor(), requestMonitor));
|
||||
} else {
|
||||
requestMonitor.done();
|
||||
}
|
||||
requestMonitor.done();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,7 @@ import java.util.concurrent.TimeUnit;
|
|||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import org.eclipse.cdt.core.IProcessInfo;
|
||||
import org.eclipse.cdt.core.IProcessList;
|
||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
|
||||
|
@ -75,6 +76,7 @@ import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
|||
import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GDBRemoteTCPLaunchTargetProvider;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.InferiorRuntimeProcess;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
|
@ -113,6 +115,8 @@ import org.eclipse.core.runtime.Status;
|
|||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.debug.core.model.IProcess;
|
||||
import org.eclipse.launchbar.core.target.ILaunchTarget;
|
||||
import org.eclipse.launchbar.core.target.launch.ITargetedLaunch;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
|
@ -126,6 +130,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IGDBProcesse
|
|||
* Each one is shown in the debug view.
|
||||
*/
|
||||
private final static int MAX_NUMBER_EXITED_PROCESS = 5;
|
||||
private final static String INVALID = "invalid"; //$NON-NLS-1$
|
||||
|
||||
// Below is the context hierarchy that is implemented between the
|
||||
// MIProcesses service and the MIRunControl service for the MI
|
||||
|
@ -1216,13 +1221,6 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IGDBProcesse
|
|||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
|
||||
if (isInitialProcess()) {
|
||||
// To be proper, set the initialProcess variable to false
|
||||
// it may be necessary for a class that extends this class
|
||||
setIsInitialProcess(false);
|
||||
}
|
||||
|
||||
// There is no groupId until we attach, so we can use the default groupId
|
||||
fContainerDmc = createContainerContext(procCtx, MIProcesses.UNIQUE_GROUP_ID);
|
||||
|
||||
|
@ -1240,6 +1238,12 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IGDBProcesse
|
|||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
if (fBackend.getSessionType() == SessionType.REMOTE && isInitialProcess()) {
|
||||
// Uncomment following and remove rm.done() once FinalLaunchSequence.stepRemoteConnection() is removed
|
||||
// connectToTarget(procCtx, rm);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
// For non-stop mode, we do a non-interrupting attach
|
||||
// Bug 333284
|
||||
boolean shouldInterrupt = true;
|
||||
|
@ -1262,6 +1266,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IGDBProcesse
|
|||
|
||||
// Store the fully formed container context so it can be returned to the caller.
|
||||
dataRm.setData(fContainerDmc);
|
||||
setIsInitialProcess(false);
|
||||
|
||||
// Initialize memory data for this process.
|
||||
IGDBMemory memory = getServicesTracker().getService(IGDBMemory.class);
|
||||
|
@ -1302,6 +1307,61 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IGDBProcesse
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 7.1
|
||||
*/
|
||||
protected void connectToTarget(IProcessDMContext procCtx, RequestMonitor rm) {
|
||||
ILaunch launch = procCtx.getAdapter(ILaunch.class);
|
||||
assert launch != null;
|
||||
if (launch != null) {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
try {
|
||||
attributes.putAll(launch.getLaunchConfiguration().getAttributes());
|
||||
} catch (CoreException e) {
|
||||
rm.done(e.getStatus());
|
||||
return;
|
||||
}
|
||||
|
||||
if (launch instanceof ITargetedLaunch) {
|
||||
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
|
||||
if (target != null) {
|
||||
attributes.putAll(target.getAttributes());
|
||||
String tcp = target.getAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, ""); //$NON-NLS-1$
|
||||
if (!tcp.isEmpty()) {
|
||||
attributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, Boolean.parseBoolean(tcp));
|
||||
} else {
|
||||
attributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
|
||||
target.getTypeId().equals(GDBRemoteTCPLaunchTargetProvider.TYPE_ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTcpConnection = CDebugUtils.getAttribute(attributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, false);
|
||||
|
||||
if (isTcpConnection) {
|
||||
String remoteTcpHost = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_HOST,
|
||||
INVALID);
|
||||
String remoteTcpPort = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_PORT,
|
||||
INVALID);
|
||||
|
||||
fCommandControl.queueCommand(fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
||||
remoteTcpHost, remoteTcpPort, true), new ImmediateDataRequestMonitor<MIInfo>(rm));
|
||||
} else {
|
||||
String serialDevice = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_DEV,
|
||||
INVALID);
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetSelect(fCommandControl.getContext(), serialDevice, true),
|
||||
new ImmediateDataRequestMonitor<MIInfo>(rm));
|
||||
}
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Cannot reconnect to target.", //$NON-NLS-1$
|
||||
null));
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 5.0 */
|
||||
protected void doReverseDebugStep(final IProcessDMContext procCtx, RequestMonitor rm) {
|
||||
// Turn on reverse debugging if it was enabled as a launch option
|
||||
|
|
|
@ -13,20 +13,17 @@
|
|||
* Marc Khouzam (Ericsson) - Workaround for Bug 352998
|
||||
* Marc Khouzam (Ericsson) - Update breakpoint handling for GDB >= 7.4 (Bug 389945)
|
||||
* Alvaro Sanchez-Leon (Ericsson) - Breakpoint Enable does not work after restarting the application (Bug 456959)
|
||||
* Jonathan Tousignant (NordiaSoft) - Remote session breakpoint (Bug 528145)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.dsf.gdb.service;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
|
||||
|
@ -48,9 +45,7 @@ import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
|
|||
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
|
||||
import org.eclipse.cdt.dsf.gdb.launching.GDBRemoteTCPLaunchTargetProvider;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
|
||||
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
|
||||
|
@ -67,12 +62,8 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIAddInferiorInfo;
|
|||
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
|
||||
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.ILaunch;
|
||||
import org.eclipse.launchbar.core.target.ILaunchTarget;
|
||||
import org.eclipse.launchbar.core.target.launch.ITargetedLaunch;
|
||||
|
||||
/**
|
||||
* Adding support for multi-process with GDB 7.2
|
||||
|
@ -176,8 +167,6 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminat
|
|||
private IGDBControl fCommandControl;
|
||||
private IGDBBackend fBackend;
|
||||
|
||||
private final static String INVALID = "invalid"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Keep track if we need to reconnect to the target
|
||||
* due to a workaround because of a GDB 7.2 bug.
|
||||
|
@ -266,15 +255,13 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminat
|
|||
|
||||
@Override
|
||||
protected boolean doIsDebuggerAttachSupported() {
|
||||
SessionType sessionType = fBackend.getSessionType();
|
||||
|
||||
// Multi-process is not applicable to post-mortem sessions (core)
|
||||
// or to non-attach remote sessions.
|
||||
if (sessionType == SessionType.CORE) {
|
||||
if (fBackend.getSessionType() == SessionType.CORE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sessionType == SessionType.REMOTE && !fBackend.getIsAttachSession()) {
|
||||
if (fBackend.getSessionType() == SessionType.REMOTE && !fBackend.getIsAttachSession()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -282,16 +269,9 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminat
|
|||
IMIRunControl runControl = getServicesTracker().getService(IMIRunControl.class);
|
||||
if (runControl != null && runControl.getRunMode() == MIRunMode.ALL_STOP) {
|
||||
// Only one process is allowed in all-stop (for now)
|
||||
return getNumConnected() == 0;
|
||||
// NOTE: when we support multi-process in all-stop mode,
|
||||
// we will need to interrupt the target to when doing the attach.
|
||||
int numConnected = getNumConnected();
|
||||
|
||||
if (numConnected == 1 && sessionType == SessionType.REMOTE) {
|
||||
// Bug 528145: Special case for remote sessions with an existing connection.
|
||||
return true;
|
||||
}
|
||||
|
||||
return numConnected == 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -325,10 +305,8 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminat
|
|||
new Step() {
|
||||
@Override
|
||||
public void execute(final RequestMonitor rm) {
|
||||
// The remote session is already connected to the process
|
||||
// Bug 528145
|
||||
if (fBackend.getSessionType() == SessionType.REMOTE
|
||||
&& doCanDetachDebuggerFromProcess()) {
|
||||
if (procCtx instanceof IMIProcessDMContext ctx
|
||||
&& MIProcesses.UNKNOWN_PROCESS_ID.equals(ctx.getProcId())) {
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
@ -469,14 +447,12 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminat
|
|||
new Step() {
|
||||
@Override
|
||||
public void execute(RequestMonitor rm) {
|
||||
// This call end the current attach to the gdbserver in remote session
|
||||
// Bug 528145
|
||||
if (fBackend.getSessionType() == SessionType.REMOTE
|
||||
&& doCanDetachDebuggerFromProcess()) {
|
||||
if (fBackend.getSessionType() == SessionType.REMOTE && isInitialProcess()) {
|
||||
// Uncomment following and remove rm.done() once FinalLaunchSequence.stepRemoteConnection() is removed
|
||||
// connectToTarget(procCtx, rm);
|
||||
rm.done();
|
||||
return;
|
||||
}
|
||||
|
||||
// For non-stop mode, we do a non-interrupting attach
|
||||
// Bug 333284
|
||||
boolean shouldInterrupt = true;
|
||||
|
@ -560,58 +536,6 @@ public class GDBProcesses_7_2 extends GDBProcesses_7_1 implements IMultiTerminat
|
|||
return false;
|
||||
}
|
||||
|
||||
private void connectToTarget(IProcessDMContext procCtx, RequestMonitor rm) {
|
||||
ILaunch launch = procCtx.getAdapter(ILaunch.class);
|
||||
assert launch != null;
|
||||
if (launch != null) {
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
try {
|
||||
attributes.putAll(launch.getLaunchConfiguration().getAttributes());
|
||||
} catch (CoreException e) {
|
||||
rm.done(e.getStatus());
|
||||
return;
|
||||
}
|
||||
|
||||
if (launch instanceof ITargetedLaunch) {
|
||||
ILaunchTarget target = ((ITargetedLaunch) launch).getLaunchTarget();
|
||||
if (target != null) {
|
||||
attributes.putAll(target.getAttributes());
|
||||
String tcp = target.getAttribute(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, ""); //$NON-NLS-1$
|
||||
if (!tcp.isEmpty()) {
|
||||
attributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, Boolean.parseBoolean(tcp));
|
||||
} else {
|
||||
attributes.put(IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP,
|
||||
target.getTypeId().equals(GDBRemoteTCPLaunchTargetProvider.TYPE_ID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTcpConnection = CDebugUtils.getAttribute(attributes,
|
||||
IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, false);
|
||||
|
||||
if (isTcpConnection) {
|
||||
String remoteTcpHost = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_HOST,
|
||||
INVALID);
|
||||
String remoteTcpPort = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_PORT,
|
||||
INVALID);
|
||||
|
||||
fCommandControl.queueCommand(fCommandFactory.createMITargetSelect(fCommandControl.getContext(),
|
||||
remoteTcpHost, remoteTcpPort, true), new ImmediateDataRequestMonitor<MIInfo>(rm));
|
||||
} else {
|
||||
String serialDevice = CDebugUtils.getAttribute(attributes, IGDBLaunchConfigurationConstants.ATTR_DEV,
|
||||
INVALID);
|
||||
|
||||
fCommandControl.queueCommand(
|
||||
fCommandFactory.createMITargetSelect(fCommandControl.getContext(), serialDevice, true),
|
||||
new ImmediateDataRequestMonitor<MIInfo>(rm));
|
||||
}
|
||||
} else {
|
||||
rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Cannot reconnect to target.", //$NON-NLS-1$
|
||||
null));
|
||||
rm.done();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void detachDebuggerFromProcess(IDMContext dmc, final RequestMonitor rm) {
|
||||
|
||||
|
|
|
@ -24,9 +24,11 @@ import java.io.FileReader;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
|
@ -192,7 +194,9 @@ public class BaseTestCase {
|
|||
*/
|
||||
public boolean isRemoteSession() {
|
||||
return launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE)
|
||||
.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE);
|
||||
.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE)
|
||||
|| launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE)
|
||||
.equals(IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE_ATTACH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -553,9 +557,6 @@ public class BaseTestCase {
|
|||
protected GdbLaunch doLaunchInner() throws Exception {
|
||||
assertNotNull("The launch configuration has not been created. Call doLaunch first.", fLaunchConfiguration);
|
||||
|
||||
boolean postMortemLaunch = launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE)
|
||||
.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE);
|
||||
|
||||
SessionEventListener sessionEventListener = new SessionEventListener(fLaunchConfiguration);
|
||||
SessionStartedListener sessionStartedListener = new SessionStartedListener() {
|
||||
@Override
|
||||
|
@ -586,12 +587,10 @@ public class BaseTestCase {
|
|||
// proceeding. All tests assume that stable initial state. Two
|
||||
// seconds is plenty; we typically get to that state in a few
|
||||
// hundred milliseconds with the tiny test programs we use.
|
||||
if (!postMortemLaunch) {
|
||||
if (isTargetExpectedToStopAfterLaunch()) {
|
||||
sessionEventListener.waitUntilTargetSuspended();
|
||||
}
|
||||
|
||||
// This should be a given if the above check passes
|
||||
if (!postMortemLaunch) {
|
||||
// This should be a given if the above check passes
|
||||
synchronized (this) {
|
||||
MIStoppedEvent initialStoppedEvent = sessionEventListener.getInitialStoppedEvent();
|
||||
Assert.assertNotNull(initialStoppedEvent);
|
||||
|
@ -617,6 +616,11 @@ public class BaseTestCase {
|
|||
return launch;
|
||||
}
|
||||
|
||||
protected boolean isTargetExpectedToStopAfterLaunch() {
|
||||
return !launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE)
|
||||
.equals(ICDTLaunchConfigurationConstants.DEBUGGER_MODE_CORE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert that the launch terminates. Callers should have already
|
||||
* terminated the launch in some way.
|
||||
|
@ -680,7 +684,19 @@ public class BaseTestCase {
|
|||
String server = (String) launchAttributes.get(ATTR_DEBUG_SERVER_NAME);
|
||||
String port = (String) launchAttributes.get(IGDBLaunchConfigurationConstants.ATTR_PORT);
|
||||
String program = (String) launchAttributes.get(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME);
|
||||
String[] commandLine = { server, ":" + port, program };
|
||||
boolean multi = Boolean.valueOf((String) launchAttributes.get(ITestConstants.LAUNCH_GDB_SERVER_MULTI));
|
||||
boolean noprogram = Boolean
|
||||
.valueOf((String) launchAttributes.get(ITestConstants.LAUNCH_GDB_SERVER_WITHOUT_PROGRAM));
|
||||
List<String> commandArgs = new ArrayList<>();
|
||||
commandArgs.add(server);
|
||||
if (multi) {
|
||||
commandArgs.add("--multi");
|
||||
}
|
||||
commandArgs.add(":" + port);
|
||||
if (!noprogram) {
|
||||
commandArgs.add(program);
|
||||
}
|
||||
String[] commandLine = commandArgs.toArray(new String[0]);
|
||||
try {
|
||||
if (GdbDebugOptions.DEBUG)
|
||||
GdbDebugOptions
|
||||
|
|
|
@ -1111,6 +1111,43 @@ public class SyncUtil {
|
|||
return query.get(TestsPlugin.massageTimeout(2000), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to return all the container DM contexts.
|
||||
*
|
||||
* <p>
|
||||
* This must NOT be called from the DSF executor.
|
||||
*
|
||||
* @return the process context
|
||||
* @throws InterruptedException
|
||||
* @throws TimeoutException
|
||||
* @throws ExecutionException
|
||||
*/
|
||||
@ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()")
|
||||
public static IContainerDMContext[] getAllContainerContexts()
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
assert !fProcessesService.getExecutor().isInExecutorThread();
|
||||
|
||||
Query<IContainerDMContext[]> query = new Query<>() {
|
||||
@Override
|
||||
protected void execute(final DataRequestMonitor<IContainerDMContext[]> rm) {
|
||||
fProcessesService.getProcessesBeingDebugged(fGdbControl.getContext(),
|
||||
new ImmediateDataRequestMonitor<IDMContext[]>() {
|
||||
@Override
|
||||
protected void handleCompleted() {
|
||||
if (isSuccess()) {
|
||||
rm.done((IContainerDMContext[]) getData());
|
||||
} else {
|
||||
rm.done(getStatus());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
fGdbControl.getExecutor().execute(query);
|
||||
return query.get(TestsPlugin.massageTimeout(2000), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to return all threads
|
||||
*
|
||||
|
@ -1126,6 +1163,22 @@ public class SyncUtil {
|
|||
|
||||
final IContainerDMContext containerDmc = SyncUtil.getContainerContext();
|
||||
|
||||
return getExecutionContexts(containerDmc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method to return all threads for given containerDmc
|
||||
* @param containerDmc
|
||||
* @return
|
||||
* @throws InterruptedException
|
||||
* @throws ExecutionException
|
||||
* @throws TimeoutException
|
||||
*/
|
||||
@ThreadSafeAndProhibitedFromDsfExecutor("fSession.getExecutor()")
|
||||
public static IMIExecutionDMContext[] getExecutionContexts(IContainerDMContext containerDmc)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
assert !fProcessesService.getExecutor().isInExecutorThread();
|
||||
|
||||
Query<IMIExecutionDMContext[]> query = new Query<>() {
|
||||
@Override
|
||||
protected void execute(final DataRequestMonitor<IMIExecutionDMContext[]> rm) {
|
||||
|
|
|
@ -64,4 +64,9 @@ public class ITestConstants {
|
|||
|
||||
// Attribute that allows a test to request not to start gdbserver even if the session is a remote one
|
||||
public static final String LAUNCH_GDB_SERVER = TestsPlugin.PLUGIN_ID + ".launchGdbServer";
|
||||
// Attribute that tells whether gdbserver should be launched without program
|
||||
public static final String LAUNCH_GDB_SERVER_WITHOUT_PROGRAM = TestsPlugin.PLUGIN_ID
|
||||
+ ".launchGdbServerWithoutProgram";
|
||||
// Attribute that tells whether gdbserver should be launched with --multi argument
|
||||
public static final String LAUNCH_GDB_SERVER_MULTI = TestsPlugin.PLUGIN_ID + ".launchGdbServerMulti";
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import org.eclipse.cdt.tests.dsf.gdb.framework.BaseParametrizedTestCase;
|
|||
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.GDBMultiNonStopRunControlTest;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.MIExpressionsNonStopTest;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.MIRunControlNonStopTargetAvailableTest;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.MultiProcessRemoteTest;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.OperationsWhileTargetIsRunningNonStopTest;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.StepIntoSelectionNonStopTest;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.tests.nonstop.ThreadStackFrameSyncTest;
|
||||
|
@ -46,7 +47,8 @@ import org.junit.runners.Suite;
|
|||
OperationsWhileTargetIsRunningNonStopTest.class, StepIntoSelectionNonStopTest.class,
|
||||
GDBRemoteTracepointsTest.class, TraceFileTest.class, GDBConsoleSynchronizingTest.class, MIMemoryTest.class,
|
||||
MIDisassemblyTest.class, GDBProcessesTest.class, PostMortemCoreTest.class, CommandTimeoutTest.class,
|
||||
ThreadStackFrameSyncTest.class, CommandLineArgsTest.class, MIAsyncErrorProcessorTests.class
|
||||
ThreadStackFrameSyncTest.class, CommandLineArgsTest.class, MIAsyncErrorProcessorTests.class,
|
||||
MultiProcessRemoteTest.class
|
||||
/* Add your test class here */
|
||||
})
|
||||
public class SuiteGdb {
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
package org.eclipse.cdt.tests.dsf.gdb.tests.nonstop;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
|
||||
import org.eclipse.cdt.dsf.concurrent.Query;
|
||||
import org.eclipse.cdt.dsf.datamodel.DMContexts;
|
||||
import org.eclipse.cdt.dsf.datamodel.IDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.IProcesses.IProcessDMContext;
|
||||
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
|
||||
import org.eclipse.cdt.dsf.gdb.IGDBLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBBackend;
|
||||
import org.eclipse.cdt.dsf.gdb.service.IGDBProcesses;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
|
||||
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
|
||||
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.BaseParametrizedTestCase;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.DefaultTimeouts;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.framework.SyncUtil.DefaultTimeouts.ETimeout;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.launching.TestsPlugin;
|
||||
import org.eclipse.cdt.tests.dsf.gdb.tests.ITestConstants;
|
||||
import org.eclipse.cdt.utils.spawner.ProcessFactory;
|
||||
import org.eclipse.core.runtime.IPath;
|
||||
import org.junit.Assume;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MultiProcessRemoteTest extends BaseParametrizedTestCase {
|
||||
private static final String EXEC_NAME = "MultiThread.exe";
|
||||
|
||||
private DsfServicesTracker fServicesTracker;
|
||||
|
||||
private IGDBProcesses fGdbProcesses;
|
||||
private ICommandControlService fCommandControl;
|
||||
private IGDBBackend fGDBBackend;
|
||||
|
||||
private List<Process> appProcesses = new ArrayList<>();
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
Assume.assumeTrue(supportsNonStop());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBeforeTest() throws Exception {
|
||||
assumeRemoteSession();
|
||||
assumeGdbVersionAtLeast(ITestConstants.SUFFIX_GDB_7_0);
|
||||
super.doBeforeTest();
|
||||
|
||||
final DsfSession session = getGDBLaunch().getSession();
|
||||
|
||||
Runnable runnable = () -> {
|
||||
fServicesTracker = new DsfServicesTracker(TestsPlugin.getBundleContext(), session.getId());
|
||||
fGdbProcesses = fServicesTracker.getService(IGDBProcesses.class);
|
||||
fCommandControl = fServicesTracker.getService(ICommandControlService.class);
|
||||
fGDBBackend = fServicesTracker.getService(IGDBBackend.class);
|
||||
};
|
||||
session.getExecutor().submit(runnable).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setLaunchAttributes() {
|
||||
super.setLaunchAttributes();
|
||||
|
||||
setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP, true);
|
||||
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME, getBinary());
|
||||
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_STOP_AT_MAIN, false);
|
||||
setLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
|
||||
IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE_ATTACH);
|
||||
setLaunchAttribute(ITestConstants.LAUNCH_GDB_SERVER_MULTI, Boolean.TRUE.toString());
|
||||
setLaunchAttribute(IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REMOTE_BINARY,
|
||||
getLaunchAttribute(ICDTLaunchConfigurationConstants.ATTR_PROGRAM_NAME));
|
||||
if (testName.getMethodName().contains("_noProgram")) {
|
||||
setLaunchAttribute(ITestConstants.LAUNCH_GDB_SERVER_WITHOUT_PROGRAM, Boolean.TRUE.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterTest() throws Exception {
|
||||
if (fServicesTracker != null)
|
||||
fServicesTracker.dispose();
|
||||
super.doAfterTest();
|
||||
for (Process p : appProcesses) {
|
||||
if (p.isAlive())
|
||||
p.destroyForcibly();
|
||||
}
|
||||
appProcesses.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isTargetExpectedToStopAfterLaunch() {
|
||||
// For some tests, we'll get stop event but not for others. Checking stop event
|
||||
// at start of launch is not required for this test class
|
||||
return false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithProgramAndStartMulipleNewExecutables() throws Throwable {
|
||||
assertEquals("Wrong number of containers at the start of launch", SyncUtil.getAllContainerContexts().length,
|
||||
getInitialProcessCount());
|
||||
|
||||
final IPath execPath = fGDBBackend.getProgramPath();
|
||||
Map<String, Object> attributes = getLaunchConfiguration().getAttributes();
|
||||
|
||||
IMIExecutionDMContext[] ctx = debugNewProcess(fGDBBackend.getProgramPath(), attributes);
|
||||
assertTrue("Process-1 is not started properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
|
||||
ctx = debugNewProcess(execPath, attributes);
|
||||
assertTrue("Process-2 is not started properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
|
||||
ctx = debugNewProcess(execPath, attributes);
|
||||
assertTrue("Process-3 is not started properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithoutProgramAndStartMulipleNewExecutables_noProgram() throws Throwable {
|
||||
launchGdbServerWithProgramAndStartMulipleNewExecutables();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithProgramAndConnectMultipleExecutables() throws Throwable {
|
||||
assertEquals("Wrong number of containers at the start of launch", SyncUtil.getAllContainerContexts().length,
|
||||
getInitialProcessCount());
|
||||
|
||||
Process process = launchApplication();
|
||||
IMIExecutionDMContext[] ctx = attachToProcess(Long.toString(process.pid()));
|
||||
assertTrue("Process-1 is not attached properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
|
||||
process = launchApplication();
|
||||
ctx = attachToProcess(Long.toString(process.pid()));
|
||||
assertTrue("Process-2 is not attached properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
|
||||
process = launchApplication();
|
||||
ctx = attachToProcess(Long.toString(process.pid()));
|
||||
assertTrue("Process-3 is not attached properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithoutProgramAndConnectMultipleExecutables_noProgram() throws Throwable {
|
||||
launchGdbServerWithProgramAndConnectMultipleExecutables();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithProgram_DebugNewExecutable_And_ConnectExecutable() throws Throwable {
|
||||
assertEquals("Wrong number of containers at the start of launch", SyncUtil.getAllContainerContexts().length,
|
||||
getInitialProcessCount());
|
||||
|
||||
final IPath execPath = fGDBBackend.getProgramPath();
|
||||
Map<String, Object> attributes = getLaunchConfiguration().getAttributes();
|
||||
|
||||
IMIExecutionDMContext[] ctx = debugNewProcess(execPath, attributes);
|
||||
assertTrue("Process-1 is not started properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
|
||||
Process process = launchApplication();
|
||||
ctx = attachToProcess(Long.toString(process.pid()));
|
||||
assertTrue("Process-2 is not attached properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithoutProgram_DebugNewExecutable_And_ConnectExecutable_noProgram() throws Throwable {
|
||||
launchGdbServerWithProgram_DebugNewExecutable_And_ConnectExecutable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithProgram_ConnectExecutable_And_DebugNewExecutable() throws Throwable {
|
||||
assertEquals("Wrong number of containers at the start of launch", SyncUtil.getAllContainerContexts().length,
|
||||
getInitialProcessCount());
|
||||
|
||||
Process process = launchApplication();
|
||||
IMIExecutionDMContext[] ctx = attachToProcess(Long.toString(process.pid()));
|
||||
assertTrue("Process-1 is not attached properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
|
||||
final IPath execPath = fGDBBackend.getProgramPath();
|
||||
Map<String, Object> attributes = getLaunchConfiguration().getAttributes();
|
||||
|
||||
ctx = debugNewProcess(execPath, attributes);
|
||||
assertTrue("Process-2 is not started properly as no threads found for it", ctx != null && ctx.length > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void launchGdbServerWithoutProgram_ConnectExecutable_And_DebugNewExecutable_noProgram() throws Throwable {
|
||||
launchGdbServerWithProgram_ConnectExecutable_And_DebugNewExecutable();
|
||||
}
|
||||
|
||||
private int getInitialProcessCount() {
|
||||
return Boolean.valueOf((String) getLaunchAttribute(ITestConstants.LAUNCH_GDB_SERVER_WITHOUT_PROGRAM)) ? 0 : 1;
|
||||
}
|
||||
|
||||
private Process launchApplication() throws IOException {
|
||||
Process process = ProcessFactory.getFactory()
|
||||
.exec(new String[] { Path.of(getBinary()).toAbsolutePath().toString() });
|
||||
if (process.isAlive()) {
|
||||
appProcesses.add(process);
|
||||
return process;
|
||||
}
|
||||
|
||||
throw new IOException("Unable to launch application");
|
||||
}
|
||||
|
||||
private static String getBinary() {
|
||||
return EXEC_PATH + EXEC_NAME;
|
||||
}
|
||||
|
||||
private IMIExecutionDMContext[] debugNewProcess(final IPath execPath, Map<String, Object> attributes)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
Query<IDMContext> query = new Query<>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<IDMContext> rm) {
|
||||
fGdbProcesses.debugNewProcess(fCommandControl.getContext(), execPath.toOSString(), attributes, rm);
|
||||
}
|
||||
};
|
||||
fGDBBackend.getExecutor().execute(query);
|
||||
IDMContext context = query.get(DefaultTimeouts.get(ETimeout.waitForStop), TimeUnit.MILLISECONDS);
|
||||
return fGdbProcesses.getExecutionContexts(DMContexts.getAncestorOfType(context, IMIContainerDMContext.class));
|
||||
}
|
||||
|
||||
private IMIExecutionDMContext[] attachToProcess(String pid)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
Query<IDMContext> query = new Query<>() {
|
||||
@Override
|
||||
protected void execute(DataRequestMonitor<IDMContext> rm) {
|
||||
IProcessDMContext procDmc = fGdbProcesses.createProcessContext(fCommandControl.getContext(), pid);
|
||||
fGdbProcesses.attachDebuggerToProcess(procDmc, getBinary(), rm);
|
||||
}
|
||||
};
|
||||
fGDBBackend.getExecutor().execute(query);
|
||||
IDMContext context = query.get(DefaultTimeouts.get(ETimeout.waitForStop), TimeUnit.MILLISECONDS);
|
||||
return fGdbProcesses.getExecutionContexts(DMContexts.getAncestorOfType(context, IMIContainerDMContext.class));
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue