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

Bug 245749 Avoid race condition by filling thread to group map of IMIProcesses service directly using new addThreadId() and removeThreadId() methods

This commit is contained in:
Marc Khouzam 2008-09-12 15:17:54 +00:00
parent fbb2135214
commit 31aeb7bca9
11 changed files with 103 additions and 128 deletions

View file

@ -182,8 +182,10 @@ public class GDBProcesses extends MIProcesses {
// This service version only handles a single process to debug, therefore, we can simply // This service version only handles a single process to debug, therefore, we can simply
// create the context describing this process ourselves. // create the context describing this process ourselves.
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
IProcessDMContext procDmc = createProcessContext(controlDmc, inferiorProcess.getPid()); // Get the groupId properly for the case of an attach
IMIExecutionGroupDMContext newGroupDmc = createExecutionGroupContext(procDmc, inferiorProcess.getPid()); String groupId = getExecutionGroupIdFromThread(null);
IProcessDMContext procDmc = createProcessContext(controlDmc, groupId);
IMIExecutionGroupDMContext newGroupDmc = createExecutionGroupContext(procDmc, groupId);
rm.setData(new IContainerDMContext[] {newGroupDmc}); rm.setData(new IContainerDMContext[] {newGroupDmc});
rm.done(); rm.done();
} else { } else {
@ -263,11 +265,18 @@ public class GDBProcesses extends MIProcesses {
@Override @Override
public String getExecutionGroupIdFromThread(String threadId) { public String getExecutionGroupIdFromThread(String threadId) {
// We need to properly return the groupId based on the pid
// to properly handle the case of an attach. See bug 244749
String groupId = null;
MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess(); MIInferiorProcess inferiorProcess = fGdb.getInferiorProcess();
if (inferiorProcess != null) { if (inferiorProcess != null) {
return inferiorProcess.getPid(); groupId = inferiorProcess.getPid();
}
if (groupId != null) {
return groupId;
} else {
return super.getExecutionGroupIdFromThread(threadId);
} }
return null;
} }
} }

View file

@ -49,8 +49,6 @@ 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.IMIDMEvent;
import org.eclipse.dd.mi.service.command.events.MIThreadCreatedEvent;
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.IThreadInfo; import org.eclipse.dd.mi.service.command.output.IThreadInfo;
@ -736,17 +734,6 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
if (e instanceof ExecutionGroupStartedDMEvent) { if (e instanceof ExecutionGroupStartedDMEvent) {
fContainerCommandCache.reset(); fContainerCommandCache.reset();
} else { } else {
// HACK figure out the thread and the group ids
// I had to HACK GDB for this
if (e instanceof IMIDMEvent) {
String threadId = ((MIThreadCreatedEvent)((IMIDMEvent)e).getMIEvent()).getStrId();
IContainerDMContext ctx = ((MIThreadCreatedEvent)((IMIDMEvent)e).getMIEvent()).getDMContext();
if (ctx instanceof IMIExecutionGroupDMContext) {
String groupId = ((IMIExecutionGroupDMContext)ctx).getGroupId();
fGroupIdMap.put(threadId, groupId);
}
}
// END HACK
fThreadCommandCache.reset(); fThreadCommandCache.reset();
} }
} }
@ -757,14 +744,6 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
if (e instanceof ExecutionGroupExitedDMEvent) { if (e instanceof ExecutionGroupExitedDMEvent) {
fContainerCommandCache.reset(); fContainerCommandCache.reset();
} else { } else {
// HACK figure out the thread and the group ids
// I had to HACK GDB for this
if (e instanceof IMIDMEvent) {
String threadId = ((MIThreadCreatedEvent)((IMIDMEvent)e).getMIEvent()).getStrId();
fGroupIdMap.remove(threadId);
}
// END HACK
fThreadCommandCache.reset(); fThreadCommandCache.reset();
} }
} }
@ -774,4 +753,12 @@ public class GDBProcesses_7_0 extends AbstractDsfService implements IMIProcesses
fThreadCommandCache.reset(context); fThreadCommandCache.reset(context);
} }
public void addThreadId(String threadId, String groupId) {
fGroupIdMap.put(threadId, groupId);
}
public void removeThreadId(String threadId) {
fGroupIdMap.remove(threadId);
}
} }

View file

@ -432,15 +432,6 @@ public class GDBControl extends AbstractMIControl implements IGDBControl {
public IPath getExecutablePath() { return fExecPath; } public IPath getExecutablePath() { return fExecPath; }
public void getInferiorProcessId(DataRequestMonitor<String> rm) {
String pid = null;
if (fInferiorProcess != null) {
pid = fInferiorProcess.getPid();
}
rm.setData(pid);
rm.done();
}
@DsfServiceEventHandler @DsfServiceEventHandler
public void eventDispatched(ICommandControlShutdownDMEvent e) { public void eventDispatched(ICommandControlShutdownDMEvent e) {
// Handle our "GDB Exited" event and stop processing commands. // Handle our "GDB Exited" event and stop processing commands.

View file

@ -433,15 +433,6 @@ public class GDBControl_7_0 extends AbstractMIControl implements IGDBControl {
public IPath getExecutablePath() { return fExecPath; } public IPath getExecutablePath() { return fExecPath; }
public void getInferiorProcessId(DataRequestMonitor<String> rm) {
String pid = null;
if (fInferiorProcess != null) {
pid = fInferiorProcess.getPid();
}
rm.setData(pid);
rm.done();
}
@DsfServiceEventHandler @DsfServiceEventHandler
public void eventDispatched(ICommandControlShutdownDMEvent e) { public void eventDispatched(ICommandControlShutdownDMEvent e) {
// Handle our "GDB Exited" event and stop processing commands. // Handle our "GDB Exited" event and stop processing commands.

View file

@ -11,7 +11,6 @@
package org.eclipse.dd.gdb.internal.provisional.service.command; package org.eclipse.dd.gdb.internal.provisional.service.command;
import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IPath;
import org.eclipse.dd.dsf.concurrent.DataRequestMonitor;
import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.concurrent.RequestMonitor;
import org.eclipse.dd.dsf.debug.service.command.ICommandControlService; import org.eclipse.dd.dsf.debug.service.command.ICommandControlService;
import org.eclipse.dd.gdb.internal.provisional.launching.GdbLaunch; import org.eclipse.dd.gdb.internal.provisional.launching.GdbLaunch;
@ -55,6 +54,4 @@ public interface IGDBControl extends ICommandControlService {
int getGDBExitCode(); int getGDBExitCode();
IPath getExecutablePath(); IPath getExecutablePath();
void getInferiorProcessId(DataRequestMonitor<String> rm);
} }

View file

@ -54,6 +54,29 @@ public interface IMIProcesses extends IProcesses
IMIExecutionGroupDMContext createExecutionGroupContext(IProcessDMContext processDmc, IMIExecutionGroupDMContext createExecutionGroupContext(IProcessDMContext processDmc,
String groupId); String groupId);
/**
* Retrieve the groupId to which this threadId belongs
*
* @param threadId The ID of the thread
* @return The ID of the group to which the specified thread belongs
*/
String getExecutionGroupIdFromThread(String threadId); String getExecutionGroupIdFromThread(String threadId);
/**
* This method should be called when a new thread is created. It allows
* to keep track of the thread to group relationship.
*
* @param threadId The ID of the new thread
* @param groupId The ID of the group to which the new thread belongs
*/
void addThreadId(String threadId, String groupId);
/**
* This method should be called when a thread exits. It is meant
* to remove the thread to group entry.
*
* @param threadId The ID of the thread that exited
*/
void removeThreadId(String threadId);
} }

View file

@ -553,8 +553,10 @@ public class MIProcesses extends AbstractDsfService implements IMIProcesses, ICa
// This service version only handles a single process to debug, therefore, we can simply // This service version only handles a single process to debug, therefore, we can simply
// create the context describing this process ourselves. // create the context describing this process ourselves.
ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class); ICommandControlDMContext controlDmc = DMContexts.getAncestorOfType(dmc, ICommandControlDMContext.class);
IProcessDMContext procDmc = createProcessContext(controlDmc, UNIQUE_GROUP_ID); // Get the groupId properly for the case of an attach
IMIExecutionGroupDMContext newGroupDmc = createExecutionGroupContext(procDmc, UNIQUE_GROUP_ID); String groupId = getExecutionGroupIdFromThread(null);
IProcessDMContext procDmc = createProcessContext(controlDmc, groupId);
IMIExecutionGroupDMContext newGroupDmc = createExecutionGroupContext(procDmc, groupId);
rm.setData(new IContainerDMContext[] {newGroupDmc}); rm.setData(new IContainerDMContext[] {newGroupDmc});
rm.done(); rm.done();
} }
@ -647,4 +649,14 @@ public class MIProcesses extends AbstractDsfService implements IMIProcesses, ICa
fContainerCommandCache.reset(context); fContainerCommandCache.reset(context);
} }
public void addThreadId(String threadId, String groupId) {
// This version of the service does not support multiple
// processes, so there is nothing to do here
}
public void removeThreadId(String threadId) {
// This version of the service does not support multiple
// processes, so there is nothing to do here
}
} }

View file

@ -106,6 +106,9 @@ public class CLIEventProcessor_7_0
if (rr != null) { if (rr != null) {
// Check if the state changed. // Check if the state changed.
String state = rr.getResultClass(); String state = rr.getResultClass();
// This is not handled properly yet
// see bug 247161
if (fInferior != null && "error".equals(state)) { //$NON-NLS-1$ if (fInferior != null && "error".equals(state)) { //$NON-NLS-1$
if (fInferior.getState() == MIInferiorProcess.State.RUNNING) { if (fInferior.getState() == MIInferiorProcess.State.RUNNING) {
fInferior.setState(MIInferiorProcess.State.STOPPED); fInferior.setState(MIInferiorProcess.State.STOPPED);

View file

@ -180,9 +180,16 @@ public class MIRunControlEventProcessor_7_0
IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class); IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
if ("thread-created".equals(miEvent)) { //$NON-NLS-1$
// Update the thread to groupId map with the new groupId
procService.addThreadId(threadId, groupId);
} else {
// It was not clear if MI would specify the groupId in the event
if (groupId == null) { if (groupId == null) {
groupId = procService.getExecutionGroupIdFromThread(threadId); groupId = procService.getExecutionGroupIdFromThread(threadId);
} }
procService.removeThreadId(threadId);
}
IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId); IProcessDMContext procDmc = procService.createProcessContext(fControlDmc, groupId);
IContainerDMContext processContainerDmc = procService.createExecutionGroupContext(procDmc, groupId); IContainerDMContext processContainerDmc = procService.createExecutionGroupContext(procDmc, groupId);
@ -193,9 +200,7 @@ public class MIRunControlEventProcessor_7_0
event = new MIThreadExitEvent(processContainerDmc, exec.getToken(), threadId); event = new MIThreadExitEvent(processContainerDmc, exec.getToken(), threadId);
} }
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties()); fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
}
} else if ("thread-group-created".equals(miEvent) || "thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$ } else if ("thread-group-created".equals(miEvent) || "thread-group-exited".equals(miEvent)) { //$NON-NLS-1$ //$NON-NLS-2$
String groupId = null; String groupId = null;
@ -222,14 +227,12 @@ public class MIRunControlEventProcessor_7_0
event = new MIThreadGroupExitedEvent(procDmc, exec.getToken(), groupId); event = new MIThreadGroupExitedEvent(procDmc, exec.getToken(), groupId);
} }
if (event != null) {
fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties()); fCommandControl.getSession().dispatchEvent(event, fCommandControl.getProperties());
} }
} }
} }
} }
} }
}
protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) { protected MIEvent<?> createEvent(String reason, MIExecAsyncOutput exec) {
String threadId = null; String threadId = null;
@ -253,6 +256,7 @@ public class MIRunControlEventProcessor_7_0
IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class); IMIProcesses procService = fServicesTracker.getService(IMIProcesses.class);
// MI does not currently provide the group-id in these events
if (groupId == null) { if (groupId == null) {
groupId = procService.getExecutionGroupIdFromThread(threadId); groupId = procService.getExecutionGroupIdFromThread(threadId);
} }
@ -319,7 +323,6 @@ public class MIRunControlEventProcessor_7_0
MIOutput output = cmdResult.getMIOutput(); MIOutput output = cmdResult.getMIOutput();
MIResultRecord rr = output.getMIResultRecord(); MIResultRecord rr = output.getMIResultRecord();
if (rr != null) { if (rr != null) {
int id = rr.getToken();
// Check if the state changed. // Check if the state changed.
String state = rr.getResultClass(); String state = rr.getResultClass();
if ("running".equals(state)) { //$NON-NLS-1$ if ("running".equals(state)) { //$NON-NLS-1$

View file

@ -108,17 +108,12 @@ public class GDBProcessesTest extends BaseTestCase {
*/ */
fSession.getExecutor().submit(new Runnable() { fSession.getExecutor().submit(new Runnable() {
public void run() { public void run() {
fGdbCtrl.getInferiorProcessId( String pid = fProcService.getExecutionGroupIdFromThread(null);
new DataRequestMonitor<String>(fSession.getExecutor(), rm) {
@Override
protected void handleSuccess() {
String pid = getData();
IProcessDMContext procDmc = fProcService.createProcessContext(fGdbCtrl.getContext(), pid); IProcessDMContext procDmc = fProcService.createProcessContext(fGdbCtrl.getContext(), pid);
fProcService.getExecutionData(procDmc, rm); fProcService.getExecutionData(procDmc, rm);
} }
}); });
}
});
/* /*
* Wait for the operation to get over * Wait for the operation to get over
*/ */

View file

@ -115,18 +115,12 @@ public class MIRunControlTest extends BaseTestCase {
*/ */
fRunCtrl.getExecutor().submit(new Runnable() { fRunCtrl.getExecutor().submit(new Runnable() {
public void run() { public void run() {
fGDBCtrl.getInferiorProcessId( String pid = fProcService.getExecutionGroupIdFromThread(null);
new DataRequestMonitor<String>(fRunCtrl.getExecutor(), rm) {
@Override
protected void handleSuccess() {
String pid = getData();
IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid); IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid);
IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid); IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid);
fRunCtrl.getExecutionContexts(groupDmc, rm); fRunCtrl.getExecutionContexts(groupDmc, rm);
} }
}); });
}
});
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
Assert.assertTrue(wait.getMessage(), wait.isOK()); Assert.assertTrue(wait.getMessage(), wait.isOK());
@ -207,18 +201,12 @@ public class MIRunControlTest extends BaseTestCase {
*/ */
fRunCtrl.getExecutor().submit(new Runnable() { fRunCtrl.getExecutor().submit(new Runnable() {
public void run() { public void run() {
fGDBCtrl.getInferiorProcessId( String pid = fProcService.getExecutionGroupIdFromThread(null);
new DataRequestMonitor<String>(fRunCtrl.getExecutor(), rmExecutionCtxts) {
@Override
protected void handleSuccess() {
String pid = getData();
IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid); IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid);
IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid); IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid);
fRunCtrl.getExecutionContexts(groupDmc, rmExecutionCtxts); fRunCtrl.getExecutionContexts(groupDmc, rmExecutionCtxts);
} }
}); });
}
});
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
Assert.assertTrue(wait.getMessage(), wait.isOK()); Assert.assertTrue(wait.getMessage(), wait.isOK());
wait.waitReset(); wait.waitReset();
@ -265,18 +253,12 @@ public class MIRunControlTest extends BaseTestCase {
*/ */
fRunCtrl.getExecutor().submit(new Runnable() { fRunCtrl.getExecutor().submit(new Runnable() {
public void run() { public void run() {
fGDBCtrl.getInferiorProcessId( String pid = fProcService.getExecutionGroupIdFromThread(null);
new DataRequestMonitor<String>(fRunCtrl.getExecutor(), rm) {
@Override
protected void handleSuccess() {
String pid = getData();
IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid); IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid);
IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid); IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid);
fRunCtrl.getExecutionData(fRunCtrl.createMIExecutionContext(groupDmc, 1), rm); fRunCtrl.getExecutionData(fRunCtrl.createMIExecutionContext(groupDmc, 1), rm);
} }
}); });
}
});
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
Assert.assertTrue(wait.getMessage(), wait.isOK()); Assert.assertTrue(wait.getMessage(), wait.isOK());
@ -490,18 +472,12 @@ public class MIRunControlTest extends BaseTestCase {
fRunCtrl.getExecutor().submit(new Runnable() { fRunCtrl.getExecutor().submit(new Runnable() {
public void run() { public void run() {
fGDBCtrl.getInferiorProcessId( String pid = fProcService.getExecutionGroupIdFromThread(null);
new DataRequestMonitor<String>(fRunCtrl.getExecutor(), rm) {
@Override
protected void handleSuccess() {
String pid = getData();
IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid); IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid);
IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid); IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid);
fRunCtrl.resume(groupDmc, rm); fRunCtrl.resume(groupDmc, rm);
} }
}); });
}
});
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
try { try {
@ -516,11 +492,7 @@ public class MIRunControlTest extends BaseTestCase {
wait.waitReset(); wait.waitReset();
fRunCtrl.getExecutor().submit(new Runnable() { fRunCtrl.getExecutor().submit(new Runnable() {
public void run() { public void run() {
fGDBCtrl.getInferiorProcessId( String pid = fProcService.getExecutionGroupIdFromThread(null);
new DataRequestMonitor<String>(fRunCtrl.getExecutor(), null) {
@Override
protected void handleCompleted() {
String pid = getData();
IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid); IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid);
IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid); IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid);
@ -528,8 +500,6 @@ public class MIRunControlTest extends BaseTestCase {
wait.waitFinished(); wait.waitFinished();
} }
}); });
}
});
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
Assert.assertFalse("Target is suspended. It should have been running", (Boolean)wait.getReturnInfo()); Assert.assertFalse("Target is suspended. It should have been running", (Boolean)wait.getReturnInfo());
@ -577,11 +547,7 @@ public class MIRunControlTest extends BaseTestCase {
wait.waitReset(); wait.waitReset();
fRunCtrl.getExecutor().submit(new Runnable() { fRunCtrl.getExecutor().submit(new Runnable() {
public void run() { public void run() {
fGDBCtrl.getInferiorProcessId( String pid = fProcService.getExecutionGroupIdFromThread(null);
new DataRequestMonitor<String>(fRunCtrl.getExecutor(), null) {
@Override
protected void handleCompleted() {
String pid = getData();
IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid); IProcessDMContext procDmc = fProcService.createProcessContext(fGDBCtrl.getContext(), pid);
IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid); IContainerDMContext groupDmc = fProcService.createExecutionGroupContext(procDmc, pid);
@ -589,8 +555,6 @@ public class MIRunControlTest extends BaseTestCase {
wait.waitFinished(); wait.waitFinished();
} }
}); });
}
});
wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER); wait.waitUntilDone(AsyncCompletionWaitor.WAIT_FOREVER);
Assert.assertFalse("Target is suspended. It should have been running", (Boolean)wait.getReturnInfo()); Assert.assertFalse("Target is suspended. It should have been running", (Boolean)wait.getReturnInfo());