1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 17:35:35 +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>();
// 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();
}
};
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 (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()));
}
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();
}
});
}
// Re-use the counting monitor and trigger it right away.
// No need to call done() in this case.
countingRm.setDoneCount(0);
} else {
countingRm.setDoneCount(1);
countingRm.done();
// 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();
}
});
}
} 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
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);
}
}
}