1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

[245749] Make the IMIProcesses service deal with the threadId to groupId map to allow for other parts of the code to have access to this knowledge.

This commit is contained in:
Marc Khouzam 2008-10-06 17:41:55 +00:00
parent 352badaaf3
commit 9920518e26
5 changed files with 147 additions and 51 deletions

View file

@ -12,6 +12,7 @@ package org.eclipse.dd.gdb.internal.provisional.service;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.core.runtime.IStatus;
@ -40,6 +41,7 @@ import org.eclipse.dd.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.dd.dsf.debug.service.ISignals.ISignalsDMContext;
import org.eclipse.dd.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
import org.eclipse.dd.dsf.debug.service.command.CommandCache;
import org.eclipse.dd.dsf.debug.service.command.IEventListener;
import org.eclipse.dd.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler;
@ -50,16 +52,23 @@ import org.eclipse.dd.mi.service.IMIContainerDMContext;
import org.eclipse.dd.mi.service.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIProcessDMContext;
import org.eclipse.dd.mi.service.IMIProcesses;
import org.eclipse.dd.mi.service.MIProcesses;
import org.eclipse.dd.mi.service.command.commands.MIListThreadGroups;
import org.eclipse.dd.mi.service.command.commands.MITargetAttach;
import org.eclipse.dd.mi.service.command.commands.MITargetDetach;
import org.eclipse.dd.mi.service.command.commands.MIThreadInfo;
import org.eclipse.dd.mi.service.command.events.MIThreadGroupCreatedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadGroupExitedEvent;
import org.eclipse.dd.mi.service.command.output.MIConst;
import org.eclipse.dd.mi.service.command.output.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo;
import org.eclipse.dd.mi.service.command.output.MINotifyAsyncOutput;
import org.eclipse.dd.mi.service.command.output.MIOOBRecord;
import org.eclipse.dd.mi.service.command.output.MIOutput;
import org.eclipse.dd.mi.service.command.output.MIResult;
import org.eclipse.dd.mi.service.command.output.MIThread;
import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo;
import org.eclipse.dd.mi.service.command.output.MIValue;
import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo;
import org.osgi.framework.BundleContext;
@ -70,7 +79,8 @@ import org.osgi.framework.BundleContext;
* which really mean it supports the new -list-thread-groups command.
*
*/
public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses, ICachingService {
public class GDBProcesses_7_0 extends AbstractDsfService
implements IMIProcesses, ICachingService, IEventListener {
// Below is the context hierarchy that is implemented between the
// MIProcesses service and the MIRunControl service for the MI
@ -329,6 +339,11 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
}
}
/**
* A map of thread id to thread group id. We use this to find out to which threadGroup a thread belongs.
*/
private Map<String, String> fThreadToGroupMap = new HashMap<String, String>();
private IGDBControl fCommandControl;
// A cache for commands about the threadGroups
@ -379,7 +394,8 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true);
getSession().addServiceEventListener(this, null);
fCommandControl.addEventListener(this);
// Register this service.
register(new String[] { IProcesses.class.getName(),
IMIProcesses.class.getName(),
@ -401,6 +417,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
public void shutdown(RequestMonitor requestMonitor) {
unregister();
getSession().removeServiceEventListener(this);
fCommandControl.removeEventListener(this);
super.shutdown(requestMonitor);
}
@ -427,10 +444,16 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
}
public IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
String groupId) {
String groupId) {
return new GDBContainerDMC(getSession().getId(), processDmc, groupId);
}
public IMIContainerDMContext createContainerContextFromThreadId(ICommandControlDMContext controlDmc, String threadId) {
String groupId = fThreadToGroupMap.get(threadId);
IProcessDMContext processDmc = createProcessContext(controlDmc, groupId);
return createContainerContext(processDmc, groupId);
}
/**
* This method obtains the model data for a given IThreadDMContext object
* which can represent a thread or a process.
@ -765,4 +788,80 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
fContainerCommandCache.reset(context);
fThreadCommandCache.reset(context);
}
/*
* Catch =thread-created/exited and =thread-group-exited events to update our
* groupId to threadId map.
*/
public void eventReceived(Object output) {
for (MIOOBRecord oobr : ((MIOutput)output).getMIOOBRecords()) {
if (oobr instanceof MINotifyAsyncOutput) {
MINotifyAsyncOutput exec = (MINotifyAsyncOutput) oobr;
String miEvent = exec.getAsyncClass();
if ("thread-created".equals(miEvent) || "thread-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
String threadId = null;
String groupId = null;
MIResult[] results = exec.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue val = results[i].getMIValue();
if (var.equals("group-id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
groupId = ((MIConst) val).getString();
}
} else if (var.equals("id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
threadId = ((MIConst) val).getString();
}
}
}
// Until GDB is officially supporting multi-process, we may not get
// a groupId. In this case, we are running single process and we'll
// need its groupId
if (groupId == null) {
groupId = MIProcesses.UNIQUE_GROUP_ID;
}
if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
// Update the thread to groupId map with the new groupId
fThreadToGroupMap.put(threadId, groupId);
} else {
fThreadToGroupMap.remove(threadId);
}
} else if ("thread-group-created".equals(miEvent) || "thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
String groupId = null;
MIResult[] results = exec.getMIResults();
for (int i = 0; i < results.length; i++) {
String var = results[i].getVariable();
MIValue val = results[i].getMIValue();
if (var.equals("id")) { //$NON-NLS-1$
if (val instanceof MIConst) {
groupId = ((MIConst) val).getString().trim();
}
}
}
if (groupId != null) {
if ("thread-group-exited".equals(miEvent)) { //$NON-NLS-1$
// Remove any entries for that group from our thread to group map
// When detaching from a group, we won't have received any thread-exited event
// but we don't want to keep those entries.
if (fThreadToGroupMap.containsValue(groupId)) {
Iterator<Map.Entry<String, String>> iterator = fThreadToGroupMap.entrySet().iterator();
while (iterator.hasNext()){
if (iterator.next().getValue().equals(groupId)) {
iterator.remove();
}
}
}
}
}
}
}
}
}
}

View file

@ -36,7 +36,7 @@ public interface IMIProcesses extends IProcesses
IProcessDMContext createProcessContext(ICommandControlDMContext controlDmc, String pid);
/**
* Create a execution context.
* Create an execution context.
*
* @param containerDmc The parent process debugging context
* @param threadDmc The parent thread context
@ -54,5 +54,14 @@ public interface IMIProcesses extends IProcesses
*/
IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
String groupId);
/**
* Create a container context based on a threadId. This implies knowledge
* of which threads belong to which container.
*
* @param controlDmc The parent command control context of this context
* @param threadId The thread id belonging to the container we want to create
*/
IMIContainerDMContext createContainerContextFromThreadId(ICommandControlDMContext controlDmc, String threadId);
}

View file

@ -393,6 +393,12 @@ public class MIProcesses extends AbstractDsfService implements IMIProcesses, ICa
return new MIContainerDMC(getSession().getId(), processDmc, groupId);
}
public IMIContainerDMContext createContainerContextFromThreadId(ICommandControlDMContext controlDmc, String threadId) {
String groupId = UNIQUE_GROUP_ID;
IProcessDMContext processDmc = createProcessContext(controlDmc, groupId);
return createContainerContext(processDmc, groupId);
}
/**
* This method obtains the model data for a given IThreadDMContext object
* which can represent a thread or a process.

View file

@ -183,7 +183,7 @@ public class MIRunControlEventProcessor
IContainerDMContext processContainerDmc = procService.createContainerContext(procDmc, groupId);
IExecutionDMContext execDmc = processContainerDmc;
if (procService != null && threadId != null) {
if (threadId != null) {
IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
execDmc = procService.createExecutionContext(processContainerDmc, threadDmc, threadId);
}

View file

@ -11,12 +11,10 @@
*******************************************************************************/
package org.eclipse.dd.mi.service.command;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.dd.dsf.datamodel.DMContexts;
import org.eclipse.dd.dsf.debug.service.IProcesses.IProcessDMContext;
import org.eclipse.dd.dsf.debug.service.IProcesses.IThreadDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
@ -91,11 +89,6 @@ public class MIRunControlEventProcessor_7_0
private final DsfServicesTracker fServicesTracker;
/**
* A map of thread id to thread group id. We use this to find out to which threadGroup a thread belongs.
*/
private Map<String, String> fThreadToGroupMap = new HashMap<String, String>();
/**
* Creates the event processor and registers it as listener with the debugger
* control.
@ -190,22 +183,16 @@ public class MIRunControlEventProcessor_7_0
}
}
if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
// Until GDB is officially supporting multi-process, we may not get
// a groupId. In this case, we are running single process and we'll
// need a groupId
if (groupId == null) {
groupId = MIProcesses.UNIQUE_GROUP_ID;
}
// Update the thread to groupId map with the new groupId
fThreadToGroupMap.put(threadId, groupId);
} else {
// It was not clear if MI would specify the groupId in the thread-exited event
if (groupId == null) {
groupId = fThreadToGroupMap.get(threadId);
}
fThreadToGroupMap.remove(threadId);
}
// Until GDB is officially supporting multi-process, we may not get
// a groupId. In this case, we are running single process and we'll
// need its groupId
if (groupId == null) {
groupId = MIProcesses.UNIQUE_GROUP_ID;
}
// Here, threads are created and removed. We cannot use the IMIProcesses service
// to map a threadId to a groupId, because there would be a race condition.
// Since we have the groupId anyway, we have no problems.
IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
if (procService != null) {
@ -245,18 +232,6 @@ public class MIRunControlEventProcessor_7_0
event = new MIThreadGroupCreatedEvent(procDmc, exec.getToken(), groupId);
} else if ("thread-group-exited".equals(miEvent)) { //$NON-NLS-1$
event = new MIThreadGroupExitedEvent(procDmc, exec.getToken(), groupId);
// Remove any entries for that group from our thread to group map
// When detaching from a group, we won't have received any thread-exited event
// but we don't want to keep those entries.
if (fThreadToGroupMap.containsValue(groupId)) {
Iterator<Map.Entry<String, String>> iterator = fThreadToGroupMap.entrySet().iterator();
while (iterator.hasNext()){
if (iterator.next().getValue().equals(groupId)) {
iterator.remove();
}
}
}
}
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
@ -291,19 +266,26 @@ public class MIRunControlEventProcessor_7_0
return null;
}
// MI does not currently provide the group-id in these events
IProcessDMContext procDmc = null;
IContainerDMContext containerDmc = null;
if (groupId == null) {
groupId = fThreadToGroupMap.get(threadId);
}
IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId);
IContainerDMContext processContainerDmc = procService.createContainerContext(procDmc, groupId);
IExecutionDMContext execDmc = processContainerDmc;
if (procService != null && threadId != null) {
IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
execDmc = procService.createExecutionContext(processContainerDmc, threadDmc, threadId);
// MI does not currently provide the group-id in these events
if (threadId != null) {
containerDmc = procService.createContainerContextFromThreadId(fControlDmc, threadId);
procDmc = DMContexts.getAncestorOfType(containerDmc, IProcessDMContext.class);
}
} else {
// This code would only trigger if the groupId was provided by MI
procDmc = procService.createProcessContext(fControlDmc, groupId);
containerDmc = procService.createContainerContext(procDmc, groupId);
}
IExecutionDMContext execDmc = containerDmc;
if (threadId != null) {
IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId);
}
MIEvent<?> event = null;
if ("breakpoint-hit".equals(reason)) { //$NON-NLS-1$
event = MIBreakpointHitEvent.parse(execDmc, exec.getToken(), exec.getMIResults());