1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-10 12:03:16 +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.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import org.eclipse.core.runtime.IStatus; 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.ISignals.ISignalsDMContext;
import org.eclipse.dd.dsf.debug.service.ISourceLookup.ISourceLookupDMContext; 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.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.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.dd.dsf.service.AbstractDsfService; import org.eclipse.dd.dsf.service.AbstractDsfService;
import org.eclipse.dd.dsf.service.DsfServiceEventHandler; 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.IMIExecutionDMContext;
import org.eclipse.dd.mi.service.IMIProcessDMContext; import org.eclipse.dd.mi.service.IMIProcessDMContext;
import org.eclipse.dd.mi.service.IMIProcesses; 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.MIListThreadGroups;
import org.eclipse.dd.mi.service.command.commands.MITargetAttach; 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.MITargetDetach;
import org.eclipse.dd.mi.service.command.commands.MIThreadInfo; 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.MIThreadGroupCreatedEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadGroupExitedEvent; 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.MIInfo;
import org.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo; 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.MIThread;
import org.eclipse.dd.mi.service.command.output.MIThreadInfoInfo; 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.eclipse.dd.mi.service.command.output.MIListThreadGroupsInfo.IThreadGroupInfo;
import org.osgi.framework.BundleContext; 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. * 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 // Below is the context hierarchy that is implemented between the
// MIProcesses service and the MIRunControl service for the MI // 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; private IGDBControl fCommandControl;
// A cache for commands about the threadGroups // A cache for commands about the threadGroups
@ -379,6 +394,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true); fThreadCommandCache.setContextAvailable(fCommandControl.getContext(), true);
getSession().addServiceEventListener(this, null); getSession().addServiceEventListener(this, null);
fCommandControl.addEventListener(this);
// Register this service. // Register this service.
register(new String[] { IProcesses.class.getName(), register(new String[] { IProcesses.class.getName(),
@ -401,6 +417,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
public void shutdown(RequestMonitor requestMonitor) { public void shutdown(RequestMonitor requestMonitor) {
unregister(); unregister();
getSession().removeServiceEventListener(this); getSession().removeServiceEventListener(this);
fCommandControl.removeEventListener(this);
super.shutdown(requestMonitor); super.shutdown(requestMonitor);
} }
@ -427,10 +444,16 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
} }
public IMIContainerDMContext createContainerContext(IProcessDMContext processDmc, public IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
String groupId) { String groupId) {
return new GDBContainerDMC(getSession().getId(), processDmc, 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 * This method obtains the model data for a given IThreadDMContext object
* which can represent a thread or a process. * which can represent a thread or a process.
@ -765,4 +788,80 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
fContainerCommandCache.reset(context); fContainerCommandCache.reset(context);
fThreadCommandCache.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); IProcessDMContext createProcessContext(ICommandControlDMContext controlDmc, String pid);
/** /**
* Create a execution context. * Create an execution context.
* *
* @param containerDmc The parent process debugging context * @param containerDmc The parent process debugging context
* @param threadDmc The parent thread context * @param threadDmc The parent thread context
@ -54,5 +54,14 @@ public interface IMIProcesses extends IProcesses
*/ */
IMIContainerDMContext createContainerContext(IProcessDMContext processDmc, IMIContainerDMContext createContainerContext(IProcessDMContext processDmc,
String groupId); 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); 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 * This method obtains the model data for a given IThreadDMContext object
* which can represent a thread or a process. * which can represent a thread or a process.

View file

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

View file

@ -11,12 +11,10 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.dd.mi.service.command; package org.eclipse.dd.mi.service.command;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; 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.IProcessDMContext;
import org.eclipse.dd.dsf.debug.service.IProcesses.IThreadDMContext; import org.eclipse.dd.dsf.debug.service.IProcesses.IThreadDMContext;
import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerDMContext;
@ -91,11 +89,6 @@ public class MIRunControlEventProcessor_7_0
private final DsfServicesTracker fServicesTracker; 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 * Creates the event processor and registers it as listener with the debugger
* control. * 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
// Until GDB is officially supporting multi-process, we may not get // a groupId. In this case, we are running single process and we'll
// a groupId. In this case, we are running single process and we'll // need its groupId
// need a groupId if (groupId == null) {
if (groupId == null) { groupId = MIProcesses.UNIQUE_GROUP_ID;
groupId = MIProcesses.UNIQUE_GROUP_ID; }
}
// Update the thread to groupId map with the new groupId // Here, threads are created and removed. We cannot use the IMIProcesses service
fThreadToGroupMap.put(threadId, groupId); // to map a threadId to a groupId, because there would be a race condition.
} else { // Since we have the groupId anyway, we have no problems.
// 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);
}
IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class); IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
if (procService != null) { if (procService != null) {
@ -245,18 +232,6 @@ public class MIRunControlEventProcessor_7_0
event = new MIThreadGroupCreatedEvent(procDmc, exec.getToken(), groupId); event = new MIThreadGroupCreatedEvent(procDmc, exec.getToken(), groupId);
} else if ("thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ } else if ("thread-group-exited".equals(miEvent)) { //$NON-NLS-1$
event = new MIThreadGroupExitedEvent(procDmc, exec.getToken(), groupId); 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()); fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
@ -291,17 +266,24 @@ public class MIRunControlEventProcessor_7_0
return null; return null;
} }
// MI does not currently provide the group-id in these events IProcessDMContext procDmc = null;
IContainerDMContext containerDmc = null;
if (groupId == null) { if (groupId == null) {
groupId = fThreadToGroupMap.get(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);
} }
IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId);
IContainerDMContext processContainerDmc = procService.createContainerContext(procDmc, groupId);
IExecutionDMContext execDmc = processContainerDmc; IExecutionDMContext execDmc = containerDmc;
if (procService != null && threadId != null) { if (threadId != null) {
IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId); IThreadDMContext threadDmc = procService.createThreadContext(procDmc, threadId);
execDmc = procService.createExecutionContext(processContainerDmc, threadDmc, threadId); execDmc = procService.createExecutionContext(containerDmc, threadDmc, threadId);
} }
MIEvent<?> event = null; MIEvent<?> event = null;