1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-10 12:03:16 +02:00

[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.
This commit is contained in:
Marc Khouzam 2009-05-11 15:27:25 +00:00
parent 364d0c3ed0
commit 98c14b14d9
2 changed files with 159 additions and 113 deletions

View file

@ -159,54 +159,76 @@ public class GdbConnectCommand implements IConnect {
final List<IProcessInfo> procInfoList = new ArrayList<IProcessInfo>(); final List<IProcessInfo> procInfoList = new ArrayList<IProcessInfo>();
// For each process, obtain its name final CountingRequestMonitor countingRm =
// Once all the names are obtained, prompt the user for the pid to use new CountingRequestMonitor(fExecutor, rm) {
final CountingRequestMonitor countingRm = @Override
new CountingRequestMonitor(fExecutor, rm) { protected void handleSuccess() {
@Override new PromptForPidJob(
protected void handleSuccess() { "Prompt for Process", procInfoList.toArray(new IProcessInfo[0]), //$NON-NLS-1$
new PromptForPidJob( new DataRequestMonitor<Integer>(fExecutor, rm) {
"Prompt for Process", procInfoList.toArray(new IProcessInfo[0]), //$NON-NLS-1$ @Override
new DataRequestMonitor<Integer>(fExecutor, rm) { protected void handleSuccess() {
@Override // New cycle, look for service again
protected void handleSuccess() { final IMIProcesses procService = fTracker.getService(IMIProcesses.class);
// New cycle, look for service again if (procService != null) {
final IMIProcesses procService = fTracker.getService(IMIProcesses.class); IProcessDMContext procDmc = procService.createProcessContext(controlCtx,
if (procService != null) { Integer.toString(getData()));
IProcessDMContext procDmc = procService.createProcessContext(controlCtx, procService.attachDebuggerToProcess(procDmc, new DataRequestMonitor<IDMContext>(fExecutor, rm));
Integer.toString(getData())); }
procService.attachDebuggerToProcess(procDmc, new DataRequestMonitor<IDMContext>(fExecutor, rm)); }
} }).schedule();
} }
}).schedule(); };
}
};
// New cycle, look for service again if (getData().length > 0 && getData()[0] instanceof IThreadDMData) {
final IProcesses procService = fTracker.getService(IProcesses.class); // 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()));
}
if (procService != null) { // Re-use the counting monitor and trigger it right away.
countingRm.setDoneCount(getData().length); // No need to call done() in this case.
countingRm.setDoneCount(0);
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();
}
});
}
} else { } else {
countingRm.setDoneCount(1); // The list of running processes does not contain the names, so
countingRm.done(); // 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();
}
});
}
} else {
// Trigger right away. No need to call done() in this case.
countingRm.setDoneCount(0);
}
} }
} }
}); });

View file

@ -148,11 +148,11 @@ public class GDBProcesses_7_0 extends AbstractDsfService
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return super.baseEquals(obj) && ((MIExecutionDMC)obj).fThreadId.equals(fThreadId); return baseEquals(obj) && ((MIExecutionDMC)obj).fThreadId.equals(fThreadId);
} }
@Override @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 @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return super.baseEquals(obj) && return baseEquals(obj) &&
(((MIContainerDMC)obj).fId == null ? fId == null : ((MIContainerDMC)obj).fId.equals(fId)); (((MIContainerDMC)obj).fId == null ? fId == null : ((MIContainerDMC)obj).fId.equals(fId));
} }
@Override @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 private class GDBContainerDMC extends MIContainerDMC
@ -245,12 +245,12 @@ public class GDBProcesses_7_0 extends AbstractDsfService
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return super.baseEquals(obj) && return baseEquals(obj) &&
(((MIThreadDMC)obj).fId == null ? fId == null : ((MIThreadDMC)obj).fId.equals(fId)); (((MIThreadDMC)obj).fId == null ? fId == null : ((MIThreadDMC)obj).fId.equals(fId));
} }
@Override @Override
public int hashCode() { return super.baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); } public int hashCode() { return baseHashCode() ^ (fId == null ? 0 : fId.hashCode()); }
} }
@Immutable @Immutable
@ -284,12 +284,12 @@ public class GDBProcesses_7_0 extends AbstractDsfService
@Override @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return super.baseEquals(obj) && return baseEquals(obj) &&
(((MIProcessDMC)obj).fId == null ? fId == null : ((MIProcessDMC)obj).fId.equals(fId)); (((MIProcessDMC)obj).fId == null ? fId == null : ((MIProcessDMC)obj).fId.equals(fId));
} }
@Override @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 * Event indicating that an container (debugged process) has started. This event
* implements the {@link IStartedMDEvent} from the IRunControl service. * implements the {@link IStartedMDEvent} from the IRunControl service.
@ -358,8 +386,11 @@ public class GDBProcesses_7_0 extends AbstractDsfService
// overlapping situations. // overlapping situations.
private CommandCache fListThreadGroupsAvailableCache; private CommandCache fListThreadGroupsAvailableCache;
// A map of process id to process names. It is filled when we get all the processes that are running // A map of process id to process names. A name is fetched whenever we start
private Map<String, String> fProcessNames = new HashMap<String, String>(); // 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$ 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) { public void getExecutionData(IThreadDMContext dmc, final DataRequestMonitor<IThreadDMData> rm) {
if (dmc instanceof IMIProcessDMContext) { 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. // For the Core session, the process is no longer running.
// Therefore, we cannot get its name with the -list-thread-groups command // Therefore, we cannot get its name with the -list-thread-groups command.
// Instead, we take it from the binary we are using. // As for id 42000, it is a special id used by GDB to indicate the real proc
String name = fBackend.getProgramPath().lastSegment(); // id is not known. This will happen in a Remote session, when we use
// Also, the pid we get from GDB is 1, which is not correct. // -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. // I haven't found a good way to get the pid yet, so let's not show it.
rm.setData(new MIThreadDMData(name, null)); id = null;
rm.done();
} else { } else {
final String id = ((IMIProcessDMContext)dmc).getProcId(); name = fDebuggedProcessNames.get(id);
String name = fProcessNames.get(id);
if (name == null) { if (name == null) {
// We don't have the name yet. Maybe we didn't fetch names yet, // We don't have the name in our map. Should not happen.
// or maybe this is a new process name = "Unknown name"; //$NON-NLS-1$
// 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();
} }
} }
rm.setData(new MIThreadDMData(name, id));
rm.done();
} else if (dmc instanceof MIThreadDMC) { } else if (dmc instanceof MIThreadDMC) {
final MIThreadDMC threadDmc = (MIThreadDMC)dmc; final MIThreadDMC threadDmc = (MIThreadDMC)dmc;
@ -741,10 +742,8 @@ public class GDBProcesses_7_0 extends AbstractDsfService
} }
private IMIContainerDMContext[] makeContainerDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] groups) { private IMIContainerDMContext[] makeContainerDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] groups) {
IProcessDMContext[] procDmcs = makeProcessDMCs(controlDmc, groups);
IMIContainerDMContext[] containerDmcs = new IMIContainerDMContext[groups.length]; 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(); String groupId = groups[i].getGroupId();
IProcessDMContext procDmc = createProcessContext(controlDmc, groupId); IProcessDMContext procDmc = createProcessContext(controlDmc, groupId);
containerDmcs[i] = createContainerContext(procDmc, groupId); containerDmcs[i] = createContainerContext(procDmc, groupId);
@ -768,10 +767,7 @@ public class GDBProcesses_7_0 extends AbstractDsfService
fListThreadGroupsAvailableCache.reset(); fListThreadGroupsAvailableCache.reset();
if (isSuccess()) { if (isSuccess()) {
for (IThreadGroupInfo groupInfo : getData().getGroupList()) { rm.setData(makeProcessDMCAndData(controlDmc, getData().getGroupList()));
fProcessNames.put(groupInfo.getPid(), groupInfo.getName());
}
rm.setData(makeProcessDMCs(controlDmc, getData().getGroupList()));
} else { } else {
rm.setData(new IProcessDMContext[0]); rm.setData(new IProcessDMContext[0]);
} }
@ -785,10 +781,13 @@ public class GDBProcesses_7_0 extends AbstractDsfService
} }
private IProcessDMContext[] makeProcessDMCs(ICommandControlDMContext controlDmc, IThreadGroupInfo[] processes) { private MIProcessDMCAndData[] makeProcessDMCAndData(ICommandControlDMContext controlDmc, IThreadGroupInfo[] processes) {
IProcessDMContext[] procDmcs = new IMIProcessDMContext[processes.length]; MIProcessDMCAndData[] procDmcs = new MIProcessDMCAndData[processes.length];
for (int i=0; i<procDmcs.length; i++) { 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; return procDmcs;
} }
@ -928,7 +927,29 @@ public class GDBProcesses_7_0 extends AbstractDsfService
} }
if (groupId != null) { 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 // 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 // When detaching from a group, we won't have received any thread-exited event
// but we don't want to keep those entries. // 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);
} }
} }
} }