diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java index 40b96c68b6c..611d5a5388f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java @@ -222,20 +222,22 @@ public class GDBRunControl_7_0_NS extends AbstractDsfService implements IMIRunCo } public StateChangeReason getReason() { - switch(getMIEvent().getType()) { - case MIRunningEvent.CONTINUE: - return StateChangeReason.USER_REQUEST; - case MIRunningEvent.NEXT: - case MIRunningEvent.NEXTI: - return StateChangeReason.STEP; - case MIRunningEvent.STEP: - case MIRunningEvent.STEPI: - return StateChangeReason.STEP; - case MIRunningEvent.FINISH: - return StateChangeReason.STEP; - case MIRunningEvent.UNTIL: - case MIRunningEvent.RETURN: - break; + if (getMIEvent() != null) { + switch(getMIEvent().getType()) { + case MIRunningEvent.CONTINUE: + return StateChangeReason.USER_REQUEST; + case MIRunningEvent.NEXT: + case MIRunningEvent.NEXTI: + return StateChangeReason.STEP; + case MIRunningEvent.STEP: + case MIRunningEvent.STEPI: + return StateChangeReason.STEP; + case MIRunningEvent.FINISH: + return StateChangeReason.STEP; + case MIRunningEvent.UNTIL: + case MIRunningEvent.RETURN: + break; + } } return StateChangeReason.UNKNOWN; } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java index 1b668fef050..28588e7f562 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_2_NS.java @@ -17,6 +17,9 @@ import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; 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.IProcessDMContext; +import org.eclipse.cdt.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.cdt.dsf.debug.service.IRunControl; import org.eclipse.cdt.dsf.debug.service.IRunControl2; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; @@ -27,6 +30,8 @@ import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext; import org.eclipse.cdt.dsf.mi.service.IMIRunControl; import org.eclipse.cdt.dsf.mi.service.command.CommandFactory; import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MIThread; +import org.eclipse.cdt.dsf.mi.service.command.output.MIThreadInfoInfo; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; @@ -41,6 +46,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS private ICommandControlService fConnection; private CommandFactory fCommandFactory; + private IGDBProcesses fProcService; /////////////////////////////////////////////////////////////////////////// // Initialization and shutdown @@ -70,6 +76,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS new Hashtable()); fConnection = getServicesTracker().getService(ICommandControlService.class); fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory(); + fProcService = getServicesTracker().getService(IGDBProcesses.class); getSession().addServiceEventListener(this, null); rm.done(); } @@ -169,4 +176,54 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS private void doResumeContainer(IMIContainerDMContext context, final RequestMonitor rm) { fConnection.queueCommand(fCommandFactory.createMIExecContinue(context), new DataRequestMonitor(getExecutor(), rm)); } + + private void refreshThreads() { + fConnection.queueCommand( + fCommandFactory.createMIThreadInfo(fConnection.getContext()), + new DataRequestMonitor(getExecutor(), null) { + @Override + protected void handleSuccess() { + MIThread[] threadList = getData().getThreadList(); + for (MIThread thread : threadList) { + String threadId = thread.getThreadId(); + IMIContainerDMContext containerDmc = + fProcService.createContainerContextFromThreadId(fConnection.getContext(), threadId); + IProcessDMContext processDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class); + IThreadDMContext threadDmc = + fProcService.createThreadContext(processDmc, threadId); + IMIExecutionDMContext execDmc = fProcService.createExecutionContext(containerDmc, threadDmc, threadId); + + MIThreadRunState threadState = fThreadRunStates.get(execDmc); + if (threadState != null) { + // We may not know this thread. This can happen when dealing with a remote + // where thread events are not reported immediately. + // However, the -list-thread-groups command we just sent will make + // GDB send those events. Therefore, we can just ignore threads we don't + // know about, and wait for those events. + if ("running".equals(thread.getState())) { //$NON-NLS-1$ + if (threadState.fSuspended == true) { + // We missed a resumed event! Send it now. + IResumedDMEvent resumedEvent = new ResumedEvent(execDmc, null); + fConnection.getSession().dispatchEvent(resumedEvent, getProperties()); + } + } else if ("stopped".equals(thread.getState())) { //$NON-NLS-1$ + if (threadState.fSuspended == false) { + // We missed a suspend event! Send it now. + ISuspendedDMEvent suspendedEvent = new SuspendedEvent(execDmc, null); + fConnection.getSession().dispatchEvent(suspendedEvent, getProperties()); + } + } else { + assert false : "Invalid thread state: " + thread.getState(); //$NON-NLS-1$ + } + } + } + } + }); + } + + @Override + public void flushCache(IDMContext context) { + super.flushCache(context); + refreshThreads(); + } }