mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[debugger] Fix stepping in several threads in suspend-thread mode
IDEA-381878 IDEA-365578 GitOrigin-RevId: 777ff16c86ef62b4f52326fca41768d5b064dbf5
This commit is contained in:
committed by
intellij-monorepo-bot
parent
277042a171
commit
2ad7f181ae
@@ -163,7 +163,8 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
|
||||
final ThreadBlockedMonitor myThreadBlockedMonitor = new ThreadBlockedMonitor(this, disposable);
|
||||
|
||||
final SteppingProgressTracker mySteppingProgressTracker = new SteppingProgressTracker(this);
|
||||
@ApiStatus.Internal
|
||||
public final SteppingProgressTracker mySteppingProgressTracker = new SteppingProgressTracker(this);
|
||||
|
||||
protected final @NotNull RunToCursorManager myRunToCursorManager;
|
||||
|
||||
@@ -215,7 +216,6 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
DebuggerStatistics.logProcessStatistics(process);
|
||||
}
|
||||
});
|
||||
mySteppingProgressTracker.installListeners();
|
||||
}
|
||||
|
||||
private DebuggerManagerThreadImpl createManagerThread() {
|
||||
@@ -2989,6 +2989,11 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
}
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public boolean isSteppingInProgress() {
|
||||
return mySteppingProgressTracker.isSteppingInProgress();
|
||||
}
|
||||
|
||||
void stopWatchingMethodReturn() {
|
||||
if (myReturnValueWatcher != null) {
|
||||
myReturnValueWatcher.disable();
|
||||
|
||||
@@ -118,12 +118,13 @@ public class JavaDebugProcess extends XDebugProcess {
|
||||
if (event == DebuggerSession.Event.CONTEXT) {
|
||||
DebuggerSession debuggerSession = newContext.getDebuggerSession();
|
||||
ThreadReferenceProxyImpl steppingThreadProxy = newContext.getThreadProxy();
|
||||
if (debuggerSession != null && steppingThreadProxy != null && debuggerSession.getState() == DebuggerSession.State.IN_STEPPING) {
|
||||
if (debuggerSession != null && debuggerSession.getState() == DebuggerSession.State.IN_STEPPING) {
|
||||
DebugProcessImpl debugProcess = debuggerSession.getProcess();
|
||||
debugProcess.getManagerThread().schedule(new DebuggerCommandImpl() {
|
||||
@Override
|
||||
protected void action() {
|
||||
JavaExecutionStack stack = new JavaExecutionStack(steppingThreadProxy, debugProcess, true);
|
||||
JavaExecutionStack stack = steppingThreadProxy != null ?
|
||||
new JavaExecutionStack(steppingThreadProxy, debugProcess, true) : null;
|
||||
getSession().positionReached(new JavaSteppingSuspendContext(debugProcess, stack));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.intellij.xdebugger.impl.XSteppingSuspendContext
|
||||
|
||||
internal class JavaSteppingSuspendContext(
|
||||
private val debugProcessImpl: DebugProcessImpl,
|
||||
private val javaExecutionStack: JavaExecutionStack
|
||||
private val javaExecutionStack: JavaExecutionStack?
|
||||
) : XSteppingSuspendContext() {
|
||||
|
||||
override fun getActiveExecutionStack(): XExecutionStack? {
|
||||
|
||||
@@ -17,17 +17,18 @@ private data class TrackedSteppingData(val stepCompetedStatus: CompletableDeferr
|
||||
internal class SteppingProgressTracker(private val debuggerProcessImpl: DebugProcessImpl) {
|
||||
private val trackedStepping = mutableListOf<TrackedSteppingData>()
|
||||
|
||||
fun installListeners() {
|
||||
debuggerProcessImpl.addDebugProcessListener(object : DebugProcessListener {
|
||||
override fun paused(suspendContext: SuspendContext) {
|
||||
val thread = suspendContext.thread
|
||||
val completedSteps = trackedStepping.filter { it.threadFilter(thread, suspendContext as SuspendContextImpl) }
|
||||
for ((stepCompetedStatus, _) in completedSteps) {
|
||||
stepCompetedStatus.complete(Unit)
|
||||
}
|
||||
trackedStepping.removeAll(completedSteps)
|
||||
}
|
||||
})
|
||||
val isSteppingInProgress: Boolean get() = trackedStepping.isNotEmpty()
|
||||
|
||||
/** returns true iff the [suspendContext] is the end of ongoing stepping */
|
||||
fun onPaused(suspendContext: SuspendContext): Boolean {
|
||||
val thread = suspendContext.thread
|
||||
val completedSteps = trackedStepping.filter { it.threadFilter(thread, suspendContext as SuspendContextImpl) }
|
||||
for ((stepCompetedStatus, _) in completedSteps) {
|
||||
stepCompetedStatus.complete(Unit)
|
||||
}
|
||||
|
||||
trackedStepping.removeAll(completedSteps)
|
||||
return completedSteps.isNotEmpty()
|
||||
}
|
||||
|
||||
fun addStepping(stepCompetedStatus: CompletableDeferred<Unit>, threadFilter: (ThreadReferenceProxy?, SuspendContextImpl) -> Boolean) {
|
||||
|
||||
@@ -100,7 +100,13 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
}
|
||||
|
||||
public void setSteppingThrough(ThreadReferenceProxyImpl threadProxy) {
|
||||
mySteppingThroughThread.set(threadProxy);
|
||||
LightOrRealThreadInfo filterThread = myDebugProcess.getRequestsManager().getFilterThread();
|
||||
if (filterThread != null && filterThread.getRealThread() != null) {
|
||||
mySteppingThroughThread.set(threadProxy);
|
||||
}
|
||||
else {
|
||||
mySteppingThroughThread.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void clearSteppingThrough() {
|
||||
@@ -531,9 +537,11 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
public void paused(final SuspendContextImpl suspendContext) {
|
||||
LOG.debug("paused");
|
||||
|
||||
boolean isSteppingEnds = myDebugProcess.mySteppingProgressTracker.onPaused(suspendContext);
|
||||
|
||||
ThreadReferenceProxyImpl currentThread = suspendContext.getEventThread();
|
||||
|
||||
if (!shouldSetAsActiveContext(suspendContext)) {
|
||||
if (!shouldSetAsActiveContext(suspendContext, isSteppingEnds)) {
|
||||
notifyThreadsRefresh();
|
||||
ThreadReferenceProxyImpl thread = suspendContext.getEventThread();
|
||||
if (thread != null) {
|
||||
@@ -683,9 +691,17 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldSetAsActiveContext(final SuspendContextImpl suspendContext) {
|
||||
private boolean shouldSetAsActiveContext(final SuspendContextImpl suspendContext, boolean isSteppingEnds) {
|
||||
if (suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_ALL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getProcess().getSuspendManager().getPausedContexts().size() > 1) {
|
||||
return isSteppingEnds;
|
||||
}
|
||||
|
||||
final ThreadReferenceProxyImpl newThread = suspendContext.getEventThread();
|
||||
if (newThread == null || suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_ALL || isSteppingThrough(newThread)) {
|
||||
if (newThread == null || suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_ALL || !myDebugProcess.isSteppingInProgress()) {
|
||||
return true;
|
||||
}
|
||||
final SuspendContextImpl currentSuspendContext = getContextManager().getContext().getSuspendContext();
|
||||
@@ -706,7 +722,7 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
ThreadReferenceProxyImpl steppingThread = getSteppingThread(suspendContext);
|
||||
|
||||
DebuggerInvocationUtil.invokeLater(getProject(), () -> {
|
||||
if (steppingThread != null && context != null) {
|
||||
if (myDebugProcess.isSteppingInProgress() && context != null) {
|
||||
switchToActiveSteppingContext(steppingThread);
|
||||
}
|
||||
else if (context != null) {
|
||||
@@ -784,7 +800,7 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
}
|
||||
}
|
||||
|
||||
private void switchToActiveSteppingContext(ThreadReferenceProxyImpl steppingThread) {
|
||||
private void switchToActiveSteppingContext(@Nullable ThreadReferenceProxyImpl steppingThread) {
|
||||
DebuggerContextImpl debuggerContext = DebuggerContextImpl.createDebuggerContext(DebuggerSession.this, null, steppingThread, null);
|
||||
getContextManager().setState(debuggerContext, State.IN_STEPPING, Event.CONTEXT, getDescription(debuggerContext));
|
||||
}
|
||||
|
||||
+1
-1
@@ -624,7 +624,7 @@ public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCa
|
||||
public void resumed(SuspendContextImpl suspendContext) {
|
||||
SuspendContextImpl pausedContext = myDebugProcess.getSuspendManager().getPausedContext();
|
||||
// do not switch context on resume inside stepping
|
||||
if (pausedContext != null && myDebugProcess.getSession().getSteppingThread(suspendContext) == null) {
|
||||
if (pausedContext != null && !myDebugProcess.isSteppingInProgress()) {
|
||||
paused(pausedContext);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user