diff options
author | Marc Khouzam | 2009-05-11 15:27:25 +0000 |
---|---|---|
committer | Marc Khouzam | 2009-05-11 15:27:25 +0000 |
commit | 98c14b14d986e9393ad0bc7dbe39a0d7f6cdc5de (patch) | |
tree | 8d11886b93ed770f7fe65d8a5fbf91c2bbc2dad9 /dsf-gdb | |
parent | 364d0c3ed0e3c59282bd22a7b5e3b1e4ccaa67b0 (diff) | |
download | org.eclipse.cdt-98c14b14d986e9393ad0bc7dbe39a0d7f6cdc5de.tar.gz org.eclipse.cdt-98c14b14d986e9393ad0bc7dbe39a0d7f6cdc5de.tar.xz org.eclipse.cdt-98c14b14d986e9393ad0bc7dbe39a0d7f6cdc5de.zip |
[275497] Return the names of all processes without having to store
them in the service. Not only is this more efficient because a single call to
the service is used, but it allows us to only store the names of processes that
we are currently debugging. That way, we know that a pid to name mapping
remains correct.
Note that I only made the change in the 7.0 version of the Processes service.
Pre-7.0, we didn't handle multi-process and therefore, we only use one name for
the process we are currently debugging, and that name is taken from the
executable binary intead.
Diffstat (limited to 'dsf-gdb')
2 files changed, 160 insertions, 114 deletions
diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbConnectCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbConnectCommand.java index bdaabae7616..66dc91cd1ad 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbConnectCommand.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/actions/GdbConnectCommand.java @@ -159,54 +159,76 @@ public class GdbConnectCommand implements IConnect { final List<IProcessInfo> procInfoList = new ArrayList<IProcessInfo>(); - // For each process, obtain its name - // Once all the names are obtained, prompt the user for the pid to use - final CountingRequestMonitor countingRm = - new CountingRequestMonitor(fExecutor, rm) { - @Override - protected void handleSuccess() { - new PromptForPidJob( - "Prompt for Process", procInfoList.toArray(new IProcessInfo[0]), //$NON-NLS-1$ - new DataRequestMonitor<Integer>(fExecutor, rm) { - @Override - protected void handleSuccess() { - // New cycle, look for service again - final IMIProcesses procService = fTracker.getService(IMIProcesses.class); - if (procService != null) { - IProcessDMContext procDmc = procService.createProcessContext(controlCtx, - Integer.toString(getData())); - procService.attachDebuggerToProcess(procDmc, new DataRequestMonitor<IDMContext>(fExecutor, rm)); - } - } - }).schedule(); - } - }; - - // New cycle, look for service again - final IProcesses procService = fTracker.getService(IProcesses.class); - - if (procService != null) { - countingRm.setDoneCount(getData().length); - - for (IProcessDMContext processCtx : getData()) { - procService.getExecutionData( - processCtx, - new DataRequestMonitor<IThreadDMData> (fExecutor, countingRm) { - @Override - protected void handleSuccess() { - int pid = 0; - try { - pid = Integer.parseInt(getData().getId()); - } catch (NumberFormatException e) { + final CountingRequestMonitor countingRm = + new CountingRequestMonitor(fExecutor, rm) { + @Override + protected void handleSuccess() { + new PromptForPidJob( + "Prompt for Process", procInfoList.toArray(new IProcessInfo[0]), //$NON-NLS-1$ + new DataRequestMonitor<Integer>(fExecutor, rm) { + @Override + protected void handleSuccess() { + // New cycle, look for service again + final IMIProcesses procService = fTracker.getService(IMIProcesses.class); + if (procService != null) { + IProcessDMContext procDmc = procService.createProcessContext(controlCtx, + Integer.toString(getData())); + procService.attachDebuggerToProcess(procDmc, new DataRequestMonitor<IDMContext>(fExecutor, rm)); + } + } + }).schedule(); + } + }; + + if (getData().length > 0 && getData()[0] instanceof IThreadDMData) { + // The list of running processes also contains the name of the processes + // This is much more efficient. Let's use it. + for (IProcessDMContext processCtx : getData()) { + IThreadDMData processData = (IThreadDMData) processCtx; + int pid = 0; + try { + pid = Integer.parseInt(processData.getId()); + } catch (NumberFormatException e) { + } + procInfoList.add(new ProcessInfo(pid, processData.getName())); + } + + // Re-use the counting monitor and trigger it right away. + // No need to call done() in this case. + countingRm.setDoneCount(0); + } else { + // The list of running processes does not contain the names, so + // we must obtain it individually + + // For each process, obtain its name + // Once all the names are obtained, prompt the user for the pid to use + + // New cycle, look for service again + final IProcesses procService = fTracker.getService(IProcesses.class); + + if (procService != null) { + countingRm.setDoneCount(getData().length); + + for (IProcessDMContext processCtx : getData()) { + procService.getExecutionData( + processCtx, + new DataRequestMonitor<IThreadDMData> (fExecutor, countingRm) { + @Override + protected void handleSuccess() { + int pid = 0; + try { + pid = Integer.parseInt(getData().getId()); + } catch (NumberFormatException e) { + } + procInfoList.add(new ProcessInfo(pid, getData().getName())); + countingRm.done(); } - procInfoList.add(new ProcessInfo(pid, getData().getName())); - countingRm.done(); - } - }); + }); + } + } else { + // Trigger right away. No need to call done() in this case. + countingRm.setDoneCount(0); } - } else { - countingRm.setDoneCount(1); - countingRm.done(); } } }); diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java index 19c440c198d..bc3c4b788c0 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBProcesses_7_0.java @@ -148,11 +148,11 @@ public class GDBProcesses_7_0 extends AbstractDsfService @Override public boolean equals(Object obj) { - return super.baseEquals(obj) && ((MIExecutionDMC)obj).fThreadId.equals(fThreadId); + return baseEquals(obj) && ((MIExecutionDMC)obj).fThreadId.equals(fThreadId); } @Override - public int hashCode() { return super.baseHashCode() ^ fThreadId.hashCode(); } + public int hashCode() { return baseHashCode() ^ fThreadId.hashCode(); } } /** @@ -191,12 +191,12 @@ public class GDBProcesses_7_0 extends AbstractDsfService @Override public boolean equals(Object obj) { - return super.baseEquals(obj) && + return baseEquals(obj) && (((MIContainerDMC)obj).fId == null ? fId == null : ((MIContainerDMC)obj).fId.equals(fId)); } @Override - public int hashCode() { return super.baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); } + public int hashCode() { return baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); } } private class GDBContainerDMC extends MIContainerDMC @@ -245,12 +245,12 @@ public class GDBProcesses_7_0 extends AbstractDsfService @Override public boolean equals(Object obj) { - return super.baseEquals(obj) && + return baseEquals(obj) && (((MIThreadDMC)obj).fId == null ? fId == null : ((MIThreadDMC)obj).fId.equals(fId)); } @Override - public int hashCode() { return super.baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); } + public int hashCode() { return baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); } } @Immutable @@ -284,12 +284,12 @@ public class GDBProcesses_7_0 extends AbstractDsfService @Override public boolean equals(Object obj) { - return super.baseEquals(obj) && + return baseEquals(obj) && (((MIProcessDMC)obj).fId == null ? fId == null : ((MIProcessDMC)obj).fId.equals(fId)); } @Override - public int hashCode() { return super.baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); } + public int hashCode() { return baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); } } /** @@ -312,6 +312,34 @@ public class GDBProcesses_7_0 extends AbstractDsfService } } + @Immutable + private static class MIProcessDMCAndData extends MIProcessDMC implements IThreadDMData { + final String fName; + + public MIProcessDMCAndData(String sessionId, ICommandControlDMContext controlDmc, String id, String name) { + super(sessionId, controlDmc, id); + fName = name; + } + + public String getId() { return getProcId(); } + public String getName() { return fName; } + public boolean isDebuggerAttached() { + return true; + } + + @Override + public String toString() { return baseToString() + ".proc[" + getId() + "," + getName() + "]"; } //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + + @Override + public boolean equals(Object obj) { + return super.equals(obj) && + (((MIProcessDMCAndData)obj).fName == null ? fName == null : ((MIProcessDMCAndData)obj).fName.equals(fName)); + } + + @Override + public int hashCode() { return super.hashCode() ^ (fName == null ? 0 : fName.hashCode()); } + } + /** * Event indicating that an container (debugged process) has started. This event * implements the {@link IStartedMDEvent} from the IRunControl service. @@ -358,8 +386,11 @@ public class GDBProcesses_7_0 extends AbstractDsfService // overlapping situations. private CommandCache fListThreadGroupsAvailableCache; - // A map of process id to process names. It is filled when we get all the processes that are running - private Map<String, String> fProcessNames = new HashMap<String, String>(); + // A map of process id to process names. A name is fetched whenever we start + // debugging a process, and removed when we stop. + // This allows us to make sure that if a pid is re-used, we will not use an + // old name for it. Bug 275497 + private Map<String, String> fDebuggedProcessNames = new HashMap<String, String>(); private static final String FAKE_THREAD_ID = "0"; //$NON-NLS-1$ @@ -501,59 +532,29 @@ public class GDBProcesses_7_0 extends AbstractDsfService public void getExecutionData(IThreadDMContext dmc, final DataRequestMonitor<IThreadDMData> rm) { if (dmc instanceof IMIProcessDMContext) { - if (fBackend.getSessionType() == SessionType.CORE) { + String id = ((IMIProcessDMContext)dmc).getProcId(); + String name = null; + if (fBackend.getSessionType() == SessionType.CORE || "42000".equals(id)) { //$NON-NLS-1$ // For the Core session, the process is no longer running. - // Therefore, we cannot get its name with the -list-thread-groups command - // Instead, we take it from the binary we are using. - String name = fBackend.getProgramPath().lastSegment(); - // Also, the pid we get from GDB is 1, which is not correct. + // Therefore, we cannot get its name with the -list-thread-groups command. + // As for id 42000, it is a special id used by GDB to indicate the real proc + // id is not known. This will happen in a Remote session, when we use + // -target-select remote instead of -target-select extended-remote. + // + // So, we take the name from the binary we are using. + name = fBackend.getProgramPath().lastSegment(); + // Also, the pid we get from GDB is 1 or 42000, which is not correct. // I haven't found a good way to get the pid yet, so let's not show it. - rm.setData(new MIThreadDMData(name, null)); - rm.done(); + id = null; } else { - final String id = ((IMIProcessDMContext)dmc).getProcId(); - String name = fProcessNames.get(id); + name = fDebuggedProcessNames.get(id); if (name == null) { - // We don't have the name yet. Maybe we didn't fetch names yet, - // or maybe this is a new process - // This is not very efficient, but GDB does not provide a way to get the name - // of a single process. - ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); - fListThreadGroupsAvailableCache.execute( - new MIListThreadGroups(controlDmc, true), - new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), rm) { - @Override - protected void handleCompleted() { - // We cannot actually cache this command since the process - // list may change. But this cache allows to avoid overlapping - // sending of this command. - fListThreadGroupsAvailableCache.reset(); - - String name = null; - if (isSuccess()) { - for (IThreadGroupInfo groupInfo : getData().getGroupList()) { - fProcessNames.put(groupInfo.getPid(), groupInfo.getName()); - if (groupInfo.getPid().equals(id)) { - name = groupInfo.getName(); - } - } - } - - if (name == null) { - // We still don't have the name... weird. - // Don't go into an infinite loop by trying again, just give up - name = "Unknown name"; //$NON-NLS-1$ - } - rm.setData(new MIThreadDMData(name, id)); - rm.done(); - } - }); - - } else { - rm.setData(new MIThreadDMData(name, id)); - rm.done(); + // We don't have the name in our map. Should not happen. + name = "Unknown name"; //$NON-NLS-1$ } } + rm.setData(new MIThreadDMData(name, id)); + rm.done(); } else if (dmc instanceof MIThreadDMC) { final MIThreadDMC threadDmc = (MIThreadDMC)dmc; @@ -741,10 +742,8 @@ public class GDBProcesses_7_0 extends AbstractDsfService } private IMIContainerDMContext[] makeContainerDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] groups) { - IProcessDMContext[] procDmcs = makeProcessDMCs(controlDmc, groups); - IMIContainerDMContext[] containerDmcs = new IMIContainerDMContext[groups.length]; - for (int i = 0; i < procDmcs.length; i++) { + for (int i = 0; i < groups.length; i++) { String groupId = groups[i].getGroupId(); IProcessDMContext procDmc = createProcessContext(controlDmc, groupId); containerDmcs[i] = createContainerContext(procDmc, groupId); @@ -768,10 +767,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService fListThreadGroupsAvailableCache.reset(); if (isSuccess()) { - for (IThreadGroupInfo groupInfo : getData().getGroupList()) { - fProcessNames.put(groupInfo.getPid(), groupInfo.getName()); - } - rm.setData(makeProcessDMCs(controlDmc, getData().getGroupList())); + rm.setData(makeProcessDMCAndData(controlDmc, getData().getGroupList())); } else { rm.setData(new IProcessDMContext[0]); } @@ -785,10 +781,13 @@ public class GDBProcesses_7_0 extends AbstractDsfService } - private IProcessDMContext[] makeProcessDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] processes) { - IProcessDMContext[] procDmcs = new IMIProcessDMContext[processes.length]; + private MIProcessDMCAndData[] makeProcessDMCAndData(ICommandControlDMContext controlDmc, IThreadGroupInfo[] processes) { + MIProcessDMCAndData[] procDmcs = new MIProcessDMCAndData[processes.length]; for (int i=0; i<procDmcs.length; i++) { - procDmcs[i] = createProcessContext(controlDmc, processes[i].getGroupId()); + procDmcs[i] = new MIProcessDMCAndData(controlDmc.getSessionId(), + controlDmc, + processes[i].getGroupId(), + processes[i].getName()); } return procDmcs; } @@ -928,7 +927,29 @@ public class GDBProcesses_7_0 extends AbstractDsfService } if (groupId != null) { - if ("thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ + if ("thread-group-created".equals(miEvent)) { //$NON-NLS-1$ + // GDB is debugging a new process. Let's fetch its name and remember it. + final String finalGroupId = groupId; + fListThreadGroupsAvailableCache.execute( + new MIListThreadGroups(fCommandControl.getContext(), true), + new DataRequestMonitor<MIListThreadGroupsInfo>(getExecutor(), null) { + @Override + protected void handleCompleted() { + // We cannot actually cache this command since the process + // list may change. But this cache allows to avoid overlapping + // sending of this command. + fListThreadGroupsAvailableCache.reset(); + + if (isSuccess()) { + for (IThreadGroupInfo groupInfo : getData().getGroupList()) { + if (groupInfo.getPid().equals(finalGroupId)) { + fDebuggedProcessNames.put(groupInfo.getPid(), groupInfo.getName()); + } + } + } + } + }); + } else 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. @@ -940,6 +961,9 @@ public class GDBProcesses_7_0 extends AbstractDsfService } } } + + // GDB is no longer debugging this process. Remove its name. + fDebuggedProcessNames.remove(groupId); } } } |