mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 353423: Need a way to refresh the thread list and state in the run control service
This commit is contained in:
parent
2810a4ed76
commit
d2c51aec89
7 changed files with 166 additions and 27 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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,10 @@ 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.MIListThreadGroupsInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo2;
|
||||
import org.eclipse.cdt.dsf.mi.service.command.output.MIThread;
|
||||
import org.eclipse.cdt.dsf.service.DsfSession;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
@ -41,6 +48,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 +78,7 @@ public class GDBRunControl_7_2_NS extends GDBRunControl_7_0_NS
|
|||
new Hashtable<String,String>());
|
||||
fConnection = getServicesTracker().getService(ICommandControlService.class);
|
||||
fCommandFactory = getServicesTracker().getService(IMICommandControl.class).getCommandFactory();
|
||||
fProcService = getServicesTracker().getService(IGDBProcesses.class);
|
||||
getSession().addServiceEventListener(this, null);
|
||||
rm.done();
|
||||
}
|
||||
|
@ -169,4 +178,63 @@ 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<MIInfo>(getExecutor(), rm));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
protected void refreshThreads() {
|
||||
fConnection.queueCommand(
|
||||
fCommandFactory.createMIListThreadGroups(fConnection.getContext(), false, true),
|
||||
new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), null) {
|
||||
@Override
|
||||
protected void handleSuccess() {
|
||||
IThreadGroupInfo[] groups = getData().getGroupList();
|
||||
for (IThreadGroupInfo group : groups) {
|
||||
if (group instanceof IThreadGroupInfo2) {
|
||||
MIThread[] threadList = ((IThreadGroupInfo2)group).getThreads();
|
||||
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 (MIThread.MI_THREAD_STATE_RUNNING.equals(thread.getState())) {
|
||||
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 (MIThread.MI_THREAD_STATE_STOPPED.equals(thread.getState())) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -677,6 +677,11 @@ public class CommandFactory {
|
|||
return new MIListThreadGroups(ctx, listAll);
|
||||
}
|
||||
|
||||
/** @since 4.1 */
|
||||
public ICommand<MIListThreadGroupsInfo> createMIListThreadGroups(ICommandControlDMContext ctx, boolean listAll, boolean recurse) {
|
||||
return new MIListThreadGroups(ctx, listAll, recurse);
|
||||
}
|
||||
|
||||
/** @since 4.0 */
|
||||
public ICommand<MIInfo> createMIRemoveInferior(ICommandControlDMContext ctx, String groupId) {
|
||||
return new MIRemoveInferior(ctx, groupId);
|
||||
|
|
|
@ -67,24 +67,42 @@ import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
|
|||
*/
|
||||
public class MIListThreadGroups extends MICommand<MIListThreadGroupsInfo> {
|
||||
|
||||
// List all groups being debugged
|
||||
/**
|
||||
* List all groups (processes) being debugged.
|
||||
*/
|
||||
public MIListThreadGroups(ICommandControlDMContext ctx) {
|
||||
this(ctx, false);
|
||||
}
|
||||
|
||||
// List all groups or threads being debugged which are children of the specified group
|
||||
/**
|
||||
* If the parameter groupId is null, list all groups (processes) being debugged.
|
||||
* If the parameter groupId is a valid group, list all threads
|
||||
* which are children of the specified group
|
||||
*/
|
||||
public MIListThreadGroups(ICommandControlDMContext ctx, String groupId) {
|
||||
this(ctx, groupId, false);
|
||||
this(ctx, groupId, false, false);
|
||||
}
|
||||
|
||||
// List all groups available on the target
|
||||
/**
|
||||
* If the parameter listAll is true, list all processes running on the
|
||||
* target (not just the debugged ones).
|
||||
* If the parameter listAll is false, list only the processes being debugged.
|
||||
*/
|
||||
public MIListThreadGroups(ICommandControlDMContext ctx, boolean listAll) {
|
||||
this(ctx, null, listAll);
|
||||
this(ctx, null, listAll, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the parameter recurse is true, list all threads of all processes.
|
||||
* @since 4.1
|
||||
*/
|
||||
public MIListThreadGroups(ICommandControlDMContext ctx, boolean listAll, boolean recurse) {
|
||||
this(ctx, null, listAll, recurse);
|
||||
}
|
||||
|
||||
// There should be no reason to have both listAll and groupId specified,
|
||||
// so this constructor is private, and exists to avoid duplicating code.
|
||||
private MIListThreadGroups(ICommandControlDMContext ctx, String groupId, boolean listAll) {
|
||||
private MIListThreadGroups(ICommandControlDMContext ctx, String groupId, boolean listAll, boolean recurse) {
|
||||
super(ctx, "-list-thread-groups"); //$NON-NLS-1$
|
||||
|
||||
assert !((groupId != null) && listAll); // see comment above
|
||||
|
@ -94,6 +112,11 @@ public class MIListThreadGroups extends MICommand<MIListThreadGroupsInfo> {
|
|||
arguments.add("--available"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (recurse) {
|
||||
arguments.add("--recurse"); //$NON-NLS-1$
|
||||
arguments.add("1"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (groupId != null) {
|
||||
assert groupId.trim().length() > 0;
|
||||
arguments.add(groupId);
|
||||
|
|
|
@ -131,6 +131,21 @@ import org.eclipse.cdt.dsf.concurrent.Immutable;
|
|||
* -list-thread-groups --available
|
||||
* ^done,groups=[{id="19418",type="process",description="gdb.7.1 -i mi testing/a.out",user="lmckhou"},{id="19424",type="process",description="/local/lmckhou/testing/a.out",user="lmckhou"},{id="19438",type="process",description="sleep 5",user="lmckhou"}]
|
||||
*
|
||||
* -list-thread-groups --recurse 1
|
||||
* ^done,groups=[{id="i2",type="process",pid="11805",executable="/home/lmckhou/Consumer",cores=["0","1"],
|
||||
* threads=[{id="6",target-id="Thread 0xb6516b70 (LWP 11811)",state="running",core="1"},
|
||||
* {id="5",target-id="Thread 0xb6d17b70 (LWP 11810)",state="running",core="1"},
|
||||
* {id="4",target-id="Thread 0xb7518b70 (LWP 11809)",
|
||||
* frame={level="0",addr="0x0804850d",func="main",args=[],file="Consumer.cc",fullname="/home/lmckhou/Consumer.cc",line="5"},
|
||||
* state="stopped",core="0"},
|
||||
* {id="3",target-id="Thread 0xb7d19b70 (LWP 11808)",state="running",core="1"},
|
||||
* {id="2",target-id="Thread 0xb7d1bb30 (LWP 11805)",state="running",core="0"}]},
|
||||
* {id="i1",type="process",pid="11793",executable="/home/lmckhProducer",cores=["0","1"],
|
||||
* threads=[{id="10",target-id="Thread 0xb6516b70 (LWP 11815)",state="running",core="0"},
|
||||
* {id="8",target-id="Thread 0xb7518b70 (LWP 11813)",state="running",core="0"},
|
||||
* {id="7",target-id="Thread 0xb7d19b70 (LWP 11812)",state="running",core="1"},
|
||||
* {id="1",target-id="Thread 0xb7d1bb30 (LWP 11793)",state="running",core="1"}]}]
|
||||
*
|
||||
* GDB 7.2
|
||||
*
|
||||
* (when no inferior is running)
|
||||
|
@ -171,8 +186,15 @@ public class MIListThreadGroupsInfo extends MIInfo {
|
|||
String getExecutable();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public interface IThreadGroupInfo2 extends IThreadGroupInfo {
|
||||
MIThread[] getThreads();
|
||||
}
|
||||
|
||||
@Immutable
|
||||
private static class ThreadGroupInfo implements IThreadGroupInfo {
|
||||
private static class ThreadGroupInfo implements IThreadGroupInfo2 {
|
||||
final String fGroupId;
|
||||
final String fDescription;
|
||||
final String fName;
|
||||
|
@ -181,9 +203,10 @@ public class MIListThreadGroupsInfo extends MIInfo {
|
|||
final String fPid;
|
||||
final String[] fCores;
|
||||
final String fExecutable;
|
||||
final MIThread[] fThreadList;
|
||||
|
||||
public ThreadGroupInfo(String id, String description, String type, String pid,
|
||||
String user, String[] cores, String exec) {
|
||||
String user, String[] cores, String exec, MIThread[] threads) {
|
||||
fGroupId = id;
|
||||
fDescription = description;
|
||||
fType = type;
|
||||
|
@ -194,6 +217,8 @@ public class MIListThreadGroupsInfo extends MIInfo {
|
|||
fExecutable = exec;
|
||||
|
||||
fName = parseName(fDescription);
|
||||
|
||||
fThreadList = threads;
|
||||
}
|
||||
|
||||
private static String parseName(String desc) {
|
||||
|
@ -225,6 +250,8 @@ public class MIListThreadGroupsInfo extends MIInfo {
|
|||
|
||||
public String getType() { return fType; }
|
||||
public String getExecutable() { return fExecutable; }
|
||||
|
||||
public MIThread[] getThreads() { return fThreadList; }
|
||||
}
|
||||
|
||||
|
||||
|
@ -274,6 +301,7 @@ public class MIListThreadGroupsInfo extends MIInfo {
|
|||
MIResult[] results = ((MITuple)values[i]).getMIResults();
|
||||
String id, desc, type, pid, exec, user;
|
||||
id = desc = type = pid = exec = user = "";//$NON-NLS-1$
|
||||
MIThread[] threads = null;
|
||||
|
||||
String[] cores = null;
|
||||
|
||||
|
@ -322,6 +350,13 @@ public class MIListThreadGroupsInfo extends MIInfo {
|
|||
String str = ((MIConst)value).getCString();
|
||||
exec = str.trim();
|
||||
}
|
||||
} else if (var.equals("threads")) { //$NON-NLS-1$
|
||||
// Staring with GDB 7.1
|
||||
// Re-use the MIThreadInfoInfo parsing
|
||||
MIValue value = result.getMIValue();
|
||||
if (value instanceof MIList) {
|
||||
threads = MIThreadInfoInfo.parseThreads(((MIList)value));
|
||||
}
|
||||
}
|
||||
}
|
||||
// In the case of -list-thread-groups --available, the pid field is not present, but the
|
||||
|
@ -332,7 +367,7 @@ public class MIListThreadGroupsInfo extends MIInfo {
|
|||
if (pid.equals("") && !desc.equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
|
||||
pid = id;
|
||||
}
|
||||
fGroupList[i] = new ThreadGroupInfo(id, desc, type, pid, user, cores, exec);
|
||||
fGroupList[i] = new ThreadGroupInfo(id, desc, type, pid, user, cores, exec, threads);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@ import org.eclipse.cdt.dsf.concurrent.Immutable;
|
|||
@Immutable
|
||||
public class MIThread {
|
||||
|
||||
/** @since 4.1 */
|
||||
public final static String MI_THREAD_STATE_RUNNING = "running"; //$NON-NLS-1$
|
||||
/** @since 4.1 */
|
||||
public final static String MI_THREAD_STATE_STOPPED = "stopped"; //$NON-NLS-1$
|
||||
|
||||
final private String fThreadId;
|
||||
final private String fTargetId;
|
||||
final private String fOsId;
|
||||
|
|
|
@ -115,7 +115,7 @@ public class MIThreadInfoInfo extends MIInfo {
|
|||
if (var.equals("threads")) { //$NON-NLS-1$
|
||||
MIValue val = results[i].getMIValue();
|
||||
if (val instanceof MIList) {
|
||||
parseThreads((MIList) val);
|
||||
fThreadList = parseThreads((MIList) val);
|
||||
}
|
||||
}
|
||||
else if (var.equals("current-thread-id")) { //$NON-NLS-1$
|
||||
|
@ -136,13 +136,14 @@ public class MIThreadInfoInfo extends MIInfo {
|
|||
// id="n",target-id="Thread 0xb7c8ab90 (LWP 7010)",frame={...},state="stopped"
|
||||
// id="n",target-id="Thread 0xb7c8eb90 (LWP 7807)",state="running"
|
||||
// id="n",target-id="Thread 162.32942",details="...",frame={...},state="stopped"
|
||||
private void parseThreads(MIList list) {
|
||||
static MIThread[] parseThreads(MIList list) {
|
||||
MIValue[] values = list.getMIValues();
|
||||
fThreadList = new MIThread[values.length];
|
||||
MIThread[] threadList = new MIThread[values.length];
|
||||
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
fThreadList[i] = MIThread.parse((MITuple) values[i]);
|
||||
threadList[i] = MIThread.parse((MITuple) values[i]);
|
||||
}
|
||||
return threadList;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue