Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 192202 Details for
Bug 337893
[multi-process][breakpoints] Setting breakpoints on a running target does not work with multi-process
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Fix for non-stop mode, single process
zpatch.targetAvailNonStop2.txt (text/plain), 16.18 KB, created by
Marc Khouzam
on 2011-03-30 11:05:07 EDT
(
hide
)
Description:
Fix for non-stop mode, single process
Filename:
MIME Type:
Creator:
Marc Khouzam
Created:
2011-03-30 11:05:07 EDT
Size:
16.18 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.cdt.dsf.gdb >Index: src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java >=================================================================== >RCS file: /cvsroot/tools/org.eclipse.cdt/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java,v >retrieving revision 1.28 >diff -u -r1.28 GDBRunControl_7_0_NS.java >--- src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java 7 Mar 2011 04:11:20 -0000 1.28 >+++ src/org/eclipse/cdt/dsf/gdb/service/GDBRunControl_7_0_NS.java 30 Mar 2011 14:56:14 -0000 >@@ -14,13 +14,15 @@ > > import java.util.HashMap; > import java.util.Hashtable; >+import java.util.LinkedList; > import java.util.Map; >-import java.util.Vector; > > import org.eclipse.cdt.core.IAddress; > import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; > import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; >+import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor; > import org.eclipse.cdt.dsf.concurrent.Immutable; >+import org.eclipse.cdt.dsf.concurrent.MultiRequestMonitor; > import org.eclipse.cdt.dsf.concurrent.RequestMonitor; > import org.eclipse.cdt.dsf.concurrent.Sequence; > import org.eclipse.cdt.dsf.concurrent.Sequence.Step; >@@ -898,25 +900,6 @@ > threadState.fStateChangeDetails = event.getDetails(); > } > >- >- /** >- * @since 3.0 >- */ >- public void executeWithTargetAvailable(IDMContext ctx, Sequence.Step[] steps, RequestMonitor rm) { >- Vector<Step> totalStepsVector = new Vector<Step>(); >- totalStepsVector.add(new IsTargetAvailableStep(ctx)); >- totalStepsVector.add(new MakeTargetAvailableStep()); >- for (Step step : steps) { >- totalStepsVector.add(step); >- } >- totalStepsVector.add(new RestoreTargetStateStep()); >- >- final Step[] totalSteps = totalStepsVector.toArray(new Step[totalStepsVector.size()]); >- getExecutor().execute(new Sequence(getExecutor(), rm) { >- @Override public Step[] getSteps() { return totalSteps; } >- }); >- } >- > /* ****************************************************************************** > * Section to support making operations even when the target is unavailable. > * >@@ -925,21 +908,264 @@ > * like breakpoints. The safe way to do it is to make sure we have at least > * one thread suspended. > * >- * Basically, we must make sure one container is suspended before making >+ * Basically, we must make sure one thread is suspended before making > * certain operations (currently breakpoints). If that is not the case, we must > * first suspend one thread, then perform the specified operations, > * and finally resume that thread.. > * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=242943 > * and https://bugs.eclipse.org/bugs/show_bug.cgi?id=282273 >- * > * ******************************************************************************/ >- private IContainerDMContext fContainerDmcToSuspend = null; >- private IMIExecutionDMContext fExecutionDmcToSuspend = null; >- private boolean fTargetAvailable = false; >+ >+ /** >+ * Utility class to store the parameters of the executeWithTargetAvailable() operations. >+ * @since 4.0 >+ */ >+ protected static class TargetAvailableOperationInfo { >+ public IDMContext ctx; >+ public Sequence.Step[] steps; >+ public RequestMonitor rm; >+ >+ public TargetAvailableOperationInfo(IDMContext ctx, Step[] steps, RequestMonitor rm) { >+ super(); >+ this.ctx = ctx; >+ this.steps = steps; >+ this.rm = rm; >+ } >+ }; >+ >+ // Keep track of if the target was available or not when we started the operation >+ private boolean fTargetAvailable; >+ // The container that needs to be suspended to perform the steps of the operation >+ private IContainerDMContext fContainerDmcToSuspend; >+ // The thread that we will actually suspend to make the container suspended. >+ private IMIExecutionDMContext fExecutionDmcToSuspend; >+ >+ // Do we currently have an executeWithTargetAvailable() operation ongoing? >+ private boolean fOngoingOperation; >+ // Are we currently executing steps passed into executeWithTargetAvailable()? >+ // This allows us to know if we can add more steps to execute or if we missed >+ // our opportunity >+ private boolean fCurrentlyExecutingSteps; >+ >+ // MultiRequestMonitor that allows us to track all the different steps we are >+ // executing. Once all steps are executed, we can complete this MultiRM and >+ // allow the global sequence to continue. >+ // Note that we couldn't use a CountingRequestMonitor because that type of RM >+ // needs to know in advance how many subRms it will track; the MultiRM allows us >+ // to receive more steps to execute continuously, and be able to upate the MultiRM. >+ private MultiRequestMonitor<RequestMonitor> fExecuteQueuedOpsStepMonitor; >+ // The number of batches of steps that are still being executing for potentially >+ // concurrent executeWithTargetAvailable() operations. >+ // Once this gets to zero, we know we have executed all the steps we were aware of >+ // and we can complete the operation. >+ private int fNumStepsStillExecuting; >+ // Queue of executeWithTargetAvailable() operations that need to be processed. >+ private LinkedList<TargetAvailableOperationInfo> fOperationsPending = new LinkedList<TargetAvailableOperationInfo>(); >+ >+ /** >+ * Returns whether the target is available to perform operations >+ * @since 4.0 >+ */ >+ protected boolean isTargetAvailable() { >+ return fTargetAvailable; >+ } >+ >+ /** @since 4.0 */ >+ protected void setTargetAvailable(boolean available) { >+ fTargetAvailable = available; >+ } >+ >+ /** >+ * Returns the container context that needs to be suspended to perform the >+ * required operation. >+ * @since 4.0 >+ */ >+ protected IContainerDMContext getContainerToSuspend() { >+ return fContainerDmcToSuspend; >+ } >+ >+ /** @since 4.0 */ >+ protected void setContainerToSuspend(IContainerDMContext context) { >+ fContainerDmcToSuspend = context; >+ } >+ >+ /** >+ * Returns the container context that needs to be suspended to perform the >+ * required operation. >+ * @since 4.0 >+ */ >+ protected IMIExecutionDMContext getExecutionToSuspend() { >+ return fExecutionDmcToSuspend; >+ } >+ >+ /** @since 4.0 */ >+ protected void setExecutionToSuspend(IMIExecutionDMContext context) { >+ fExecutionDmcToSuspend = context; >+ } >+ >+ /** >+ * Returns whether there is currently an ExecuteWithTargetAvailable() operation ongoing. >+ * @since 4.0 >+ */ >+ protected boolean isTargetAvailableOperationOngoing() { >+ return fOngoingOperation; >+ } >+ >+ /** @since 4.0 */ >+ protected void setTargetAvailableOperationOngoing(boolean ongoing) { >+ fOngoingOperation = ongoing; >+ } >+ >+ /** >+ * Returns whether we are current in the process of executing the steps >+ * that were passed to ExecuteWithTargetAvailable(). >+ * When this value is true, we can send more steps to be executed. >+ * @since 4.0 >+ */ >+ protected boolean isCurrentlyExecutingSteps() { >+ return fCurrentlyExecutingSteps; >+ } >+ >+ /** @since 4.0 */ >+ protected void setCurrentlyExecutingSteps(boolean executing) { >+ fCurrentlyExecutingSteps = executing; >+ } >+ >+ /** >+ * Returns the requestMonitor that will be run once all steps sent to >+ * ExecuteWithTargetAvailable() have been executed. >+ * @since 4.0 >+ */ >+ protected MultiRequestMonitor<RequestMonitor> getExecuteQueuedStepsRM() { >+ return fExecuteQueuedOpsStepMonitor; >+ } >+ >+ /** @since 4.0 */ >+ protected void setExecuteQueuedStepsRM(MultiRequestMonitor<RequestMonitor> rm) { >+ fExecuteQueuedOpsStepMonitor = rm; >+ } >+ >+ >+ /** >+ * Returns the number of batches of steps sent to ExecuteWithTargetAvailable() >+ * that are still executing. Once this number reaches zero, we can complete >+ * the overall ExecuteWithTargetAvailable() operation. >+ * @since 4.0 >+ */ >+ protected int getNumStepsStillExecuting() { >+ return fNumStepsStillExecuting; >+ } >+ >+ /** @since 4.0 */ >+ protected void setNumStepsStillExecuting(int num) { >+ fNumStepsStillExecuting = num; >+ } >+ >+ /** >+ * Returns the queue of executeWithTargetAvailable() operations that still need to be processed >+ * @since 4.0 >+ */ >+ protected LinkedList<TargetAvailableOperationInfo> getOperationsPending() { >+ return fOperationsPending; >+ } >+ >+ /** >+ * This method takes care of executing a batch of steps that were passed to >+ * ExecuteWithTargetAvailable(). The method is used to track the progress >+ * of all these batches of steps, so that we know exactly when all of them >+ * have been completed and the global sequence can be completed. >+ * @since 4.0 >+ */ >+ protected void executeSteps(final TargetAvailableOperationInfo info) { >+ fNumStepsStillExecuting++; >+ >+ // This RM propagates any error to the original rm of the actual steps. >+ // Even in case of errors for these steps, we want to continue the overall sequence >+ RequestMonitor stepsRm = new RequestMonitor(ImmediateExecutor.getInstance(), null) { >+ @Override >+ protected void handleCompleted() { >+ info.rm.setStatus(getStatus()); >+ // It is important to call rm.done() right away. >+ // This is because some other operation we are performing might be waiting >+ // for this one to be done. If we try to wait for the entire sequence to be >+ // done, then we will never finish because one monitor will never show as >+ // done, waiting for the second one. >+ info.rm.done(); >+ >+ fExecuteQueuedOpsStepMonitor.requestMonitorDone(this); >+ fNumStepsStillExecuting--; >+ if (fNumStepsStillExecuting == 0) { >+ fExecuteQueuedOpsStepMonitor.doneAdding(); >+ } >+ } >+ }; >+ >+ fExecuteQueuedOpsStepMonitor.add(stepsRm); > >+ getExecutor().execute(new Sequence(getExecutor(), stepsRm) { >+ @Override public Step[] getSteps() { return info.steps; } >+ }); >+ } >+ > /** > * @since 3.0 > */ >+ public void executeWithTargetAvailable(IDMContext ctx, final Sequence.Step[] steps, final RequestMonitor rm) { >+ if (!fOngoingOperation) { >+ // We are the first operation of this kind currently requested >+ // so we need to start the sequence >+ fOngoingOperation = true; >+ >+ // We always go through our queue, even if we only have a single call to this method >+ fOperationsPending.add(new TargetAvailableOperationInfo(ctx, steps, rm)); >+ >+ // Steps that need to be executed to perform the operation >+ final Step[] sequenceSteps = new Step[] { >+ new IsTargetAvailableStep(ctx), >+ new MakeTargetAvailableStep(), >+ new ExecuteQueuedOperationsStep(), >+ new RestoreTargetStateStep(), >+ }; >+ >+ // Once all the sequence is completed, we need to see if we have received >+ // another request that we now need to process >+ RequestMonitor sequenceCompletedRm = new RequestMonitor(getExecutor(), null) { >+ @Override >+ protected void handleCompleted() { >+ fOngoingOperation = false; >+ >+ if (fOperationsPending.size() > 0) { >+ // Darn, more operations came in. Trigger their processing >+ // by calling executeWithTargetAvailable() on the last one >+ TargetAvailableOperationInfo info = fOperationsPending.removeLast(); >+ executeWithTargetAvailable(info.ctx, info.steps, info.rm); >+ } >+ // no other rm.done() needs to be called, they have all been handled already >+ } >+ }; >+ >+ getExecutor().execute(new Sequence(getExecutor(), sequenceCompletedRm) { >+ @Override public Step[] getSteps() { return sequenceSteps; } >+ }); >+ } else { >+ // We are currently already executing such an operation >+ // If we are still in the process of executing steps, let's include this new set of steps. >+ // This is important because some steps may depend on these new ones. >+ if (fCurrentlyExecutingSteps) { >+ executeSteps(new TargetAvailableOperationInfo(ctx, steps, rm)); >+ } else { >+ // Too late to execute the new steps, so queue them for later >+ fOperationsPending.add(new TargetAvailableOperationInfo(ctx, steps, rm)); >+ } >+ } >+ } >+ >+ >+ /** >+ * This part of the sequence verifies if the execution context of interest >+ * is suspended or not. >+ * @since 3.0 >+ */ > protected class IsTargetAvailableStep extends Sequence.Step { > final IDMContext fCtx; > >@@ -949,17 +1175,17 @@ > > @Override > public void execute(final RequestMonitor rm) { >- fContainerDmcToSuspend = DMContexts.getAncestorOfType(fCtx, IContainerDMContext.class); >+ fContainerDmcToSuspend = DMContexts.getAncestorOfType(fCtx, IMIContainerDMContext.class); > if (fContainerDmcToSuspend != null) { >- // In non-stop, we don't actually need this particular process to be suspended, >- // all we need is one of any of the processes to be suspended. >- // However, for efficiency, we can first check if the process in question >- // is suspended. >- if (isSuspended(fContainerDmcToSuspend)) { >- fTargetAvailable = true; >+ String groupId = ((IMIContainerDMContext)fContainerDmcToSuspend).getGroupId(); >+ if (groupId != null && groupId.length() > 0) { >+ // If we have a fully formed containerDmc, we can use it directly. >+ fTargetAvailable = isSuspended(fContainerDmcToSuspend); > rm.done(); > return; > } >+ // else, the container is not fully formed, so let's fetch it below, since >+ // we know we are running single-process and there is only one process > } > > // If we get here, we have to get the list of processes to know if any of >@@ -974,7 +1200,7 @@ > assert getData() != null; > > if (getData().length == 0) { >- // Happens at startup, starting with GDB 7.0 >+ // Happens at startup, starting with GDB 7.0. > // This means the target is available > fTargetAvailable = true; > } else { >@@ -995,12 +1221,14 @@ > }; > > /** >+ * If the execution context of interest is not suspended, this step >+ * will interrupt it. > * @since 3.0 > */ > protected class MakeTargetAvailableStep extends Sequence.Step { > @Override > public void execute(final RequestMonitor rm) { >- if (!fTargetAvailable) { >+ if (!isTargetAvailable()) { > // Instead of suspending the entire process, let's find its first thread and use that > IProcesses processControl = getServicesTracker().getService(IProcesses.class); > processControl.getProcessesBeingDebugged( >@@ -1028,7 +1256,6 @@ > super.handleFailure(); > }; > }); >- > } > }); > } else { >@@ -1043,12 +1270,50 @@ > }; > > /** >+ * This step of the sequence takes care of executing all the steps that >+ * were passed to ExecuteWithTargetAvailable(). >+ * @since 4.0 >+ */ >+ protected class ExecuteQueuedOperationsStep extends Sequence.Step { >+ @Override >+ public void execute(final RequestMonitor rm) { >+ fCurrentlyExecutingSteps = true; >+ >+ // It is important to use an ImmediateExecutor for this RM, to make sure we don't risk getting a new >+ // call to ExecuteWithTargetAvailable() when we just finished executing the steps. >+ fExecuteQueuedOpsStepMonitor = new MultiRequestMonitor<RequestMonitor>(ImmediateExecutor.getInstance(), rm) { >+ @Override >+ protected void handleCompleted() { >+ assert fOperationsPending.size() == 0; >+ >+ // We don't handle errors here. Instead, we have already propagated any >+ // errors to each rm for each set of steps >+ >+ fCurrentlyExecutingSteps = false; >+ // Continue the sequence >+ rm.done(); >+ } >+ }; >+ // Tell the RM that we need to confirm when we are done adding sub-rms >+ fExecuteQueuedOpsStepMonitor.requireDoneAdding(); >+ >+ // All pending operations are independent of each other so we can >+ // run them concurrently. >+ while (fOperationsPending.size() > 0) { >+ executeSteps(fOperationsPending.poll()); >+ } >+ } >+ }; >+ >+ /** >+ * If the sequence had to interrupt the execution context of interest, >+ * this step will resume it again to reach the same state as when we started. > * @since 3.0 > */ > protected class RestoreTargetStateStep extends Sequence.Step { > @Override > public void execute(final RequestMonitor rm) { >- if (!fTargetAvailable) { >+ if (!isTargetAvailable()) { > assert fDisableNextRunningEventDmc == null; > fDisableNextRunningEventDmc = fExecutionDmcToSuspend; > >@@ -1089,6 +1354,10 @@ > } > }; > >+ /* ****************************************************************************** >+ * End of section to support operations even when the target is unavailable. >+ * ******************************************************************************/ >+ > /////////////////////////////////////////////////////////////////////////// > // Event handlers > ///////////////////////////////////////////////////////////////////////////
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
marc.khouzam
:
iplog-
Actions:
View
|
Diff
Attachments on
bug 337893
:
192028
|
192029
|
192038
| 192202 |
192418
|
192419
|
192606
|
192993
|
193212