diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java index a265c0d3bc9b..86d2d936f322 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java @@ -638,7 +638,7 @@ public class DebugProcessEvents extends DebugProcessImpl { @Override public void contextAction(@NotNull SuspendContextImpl suspendContext) { logSuspendContext(suspendContext, () -> "start locatable event processing"); - final SuspendManager suspendManager = getSuspendManager(); + final SuspendManagerImpl suspendManager = (SuspendManagerImpl)getSuspendManager(); final LocatableEventRequestor requestor = (LocatableEventRequestor)RequestManagerImpl.findRequestor(event.request()); ThreadReferenceProxyImpl threadProxy = suspendContext.getThread(); @@ -671,7 +671,10 @@ public class DebugProcessEvents extends DebugProcessImpl { suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD && myRunToCursorManager.shouldTryToPauseAnotherHit(suspendContext)) { postponeSuspendRunToCursorBP = true; - } else { + } else if (mySteppingProgressTracker.isSuspendAllStepping() || + !suspendManager.getSuspendAllContexts().isEmpty() || + requestor instanceof SyntheticBreakpoint + ) { // notify only if the current session is not one with evaluations hidden from the user if (!checkContextIsFromImplicitThread(suspendContext)) { notifySkippedBreakpoints(event, SkippedBreakpointReason.STEPPING); @@ -679,6 +682,8 @@ public class DebugProcessEvents extends DebugProcessImpl { logSuspendContext(suspendContext, () -> "Skip breakpoint because of filter " + filter); suspendManager.voteResume(suspendContext); return; + } else { + suspendContext.threadFilterWasPassed = false; } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SteppingProgressTracker.kt b/java/debugger/impl/src/com/intellij/debugger/engine/SteppingProgressTracker.kt index dc4e4c47b010..de5930c9224f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/SteppingProgressTracker.kt +++ b/java/debugger/impl/src/com/intellij/debugger/engine/SteppingProgressTracker.kt @@ -7,18 +7,21 @@ import com.intellij.debugger.engine.jdi.ThreadReferenceProxy import com.intellij.debugger.impl.DebuggerUtilsAsync import com.intellij.debugger.impl.PrioritizedTask import com.intellij.debugger.jdi.ThreadReferenceProxyImpl +import com.intellij.debugger.settings.DebuggerSettings import com.sun.jdi.request.EventRequest import kotlinx.coroutines.CompletableDeferred import org.jetbrains.annotations.Nls import java.util.concurrent.CompletableFuture -private data class TrackedSteppingData(val stepCompetedStatus: CompletableDeferred, val threadFilter: (ThreadReferenceProxy?, SuspendContextImpl) -> Boolean) +private data class TrackedSteppingData(val stepCompetedStatus: CompletableDeferred, val isSuspendAllStepping: Boolean, val threadFilter: (ThreadReferenceProxy?, SuspendContextImpl) -> Boolean) internal class SteppingProgressTracker(private val debuggerProcessImpl: DebugProcessImpl) { private val trackedStepping = mutableListOf() val isSteppingInProgress: Boolean get() = trackedStepping.isNotEmpty() + val isSuspendAllStepping: Boolean get() = trackedStepping.any { it.isSuspendAllStepping } + /** returns true iff the [suspendContext] is the end of ongoing stepping */ fun onPaused(suspendContext: SuspendContext): Boolean { val thread = suspendContext.thread @@ -31,8 +34,8 @@ internal class SteppingProgressTracker(private val debuggerProcessImpl: DebugPro return completedSteps.isNotEmpty() } - fun addStepping(stepCompetedStatus: CompletableDeferred, threadFilter: (ThreadReferenceProxy?, SuspendContextImpl) -> Boolean) { - trackedStepping.add(TrackedSteppingData(stepCompetedStatus, threadFilter)) + fun addStepping(stepCompetedStatus: CompletableDeferred, isSuspendAllStepping: Boolean, threadFilter: (ThreadReferenceProxy?, SuspendContextImpl) -> Boolean) { + trackedStepping.add(TrackedSteppingData(stepCompetedStatus, isSuspendAllStepping, threadFilter)) } } @@ -41,6 +44,8 @@ private class CancelingSteppingListener : SteppingListener { val debuggerProcessImpl: DebugProcessImpl = suspendContext.debugProcess val filter: LightOrRealThreadInfo? = debuggerProcessImpl.requestsManager.filterThread + val isSuspendAllPolicy = suspendContext.suspendPolicyFromRequestors == DebuggerSettings.SUSPEND_ALL + val threadForStepping: ThreadReferenceProxyImpl? = if (filter != null) suspendContext.virtualMachineProxy.getThreadReferenceProxy(filter.realThread) else suspendContext.thread @@ -76,8 +81,10 @@ private class CancelingSteppingListener : SteppingListener { } val tracker = suspendContext.debugProcess.mySteppingProgressTracker - tracker.addStepping(stepCompetedStatus) { thread, suspendContext -> - thread == null || filter != null && filter.checkSameThread(thread.threadReference, suspendContext) || thread == threadForStepping + tracker.addStepping(stepCompetedStatus, isSuspendAllPolicy) { thread, suspendContext -> + thread == null + || (filter != null && filter.checkSameThread(thread.threadReference, suspendContext)) + || (filter == null && thread == threadForStepping) } } } diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextImpl.kt b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextImpl.kt index 10d65ef235ef..13b7cd31619c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextImpl.kt +++ b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextImpl.kt @@ -62,6 +62,9 @@ abstract class SuspendContextImpl @ApiStatus.Internal constructor( @JvmField protected var mySteppingThreadForResumeOneSteppingCurrentMode: ThreadReferenceProxyImpl? = null + @JvmField + internal var threadFilterWasPassed = true + @get:ApiStatus.Internal @set:ApiStatus.Internal var lightThreadFilter: Any? = null @@ -268,7 +271,7 @@ abstract class SuspendContextImpl @ApiStatus.Internal constructor( @MagicConstant(flagsFromClass = EventRequest::class) override fun getSuspendPolicy(): Int = mySuspendPolicy - val suspendPolicyFromRequestors: String? + val suspendPolicyFromRequestors: String get() { if (mySuspendPolicy == EventRequest.SUSPEND_ALL) return DebuggerSettings.SUSPEND_ALL val eventSet = myEventSet diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java index 8ea96d16748e..ef39e75e709f 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendManagerImpl.java @@ -324,7 +324,6 @@ public class SuspendManagerImpl implements SuspendManager { } else { LOG.debug("vote paused"); - myDebugProcess.cancelSteppingBreakpoints(); if (!Registry.is("debugger.keep.step.requests")) { ThreadReferenceProxyImpl thread = suspendContext.getEventThread(); myDebugProcess.deleteStepRequests(suspendContext.getVirtualMachineProxy().eventRequestManager(), diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java index e005fff1a198..adf320988fd4 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java @@ -559,13 +559,22 @@ public final class DebuggerSession implements AbstractDebuggerSession { return; } else { - currentThread = mySteppingThroughThread.get(); + if (suspendContext.threadFilterWasPassed) { + currentThread = mySteppingThroughThread.get(); + } + else { + return; + } } } else { - setSteppingThrough(currentThread); + if (suspendContext.threadFilterWasPassed) { + setSteppingThrough(currentThread); + } } + myDebugProcess.cancelSteppingBreakpoints(); + final StackFrameContext positionContext; SourcePosition position; @@ -702,11 +711,15 @@ public final class DebuggerSession implements AbstractDebuggerSession { final ThreadReferenceProxyImpl newThread = suspendContext.getEventThread(); if (newThread == null || suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_ALL || !myDebugProcess.isSteppingInProgress()) { - return true; + if (suspendContext.threadFilterWasPassed) { + return true; + } } final SuspendContextImpl currentSuspendContext = getContextManager().getContext().getSuspendContext(); if (currentSuspendContext == null || currentSuspendContext.isResumed()) { - return mySteppingThroughThread.get() == null; + if (suspendContext.threadFilterWasPassed) { + return mySteppingThroughThread.get() == null; + } } if (enableBreakpointsDuringEvaluation()) { final ThreadReferenceProxyImpl currentThread = currentSuspendContext.getThread();