mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
[debugger] IDEA-338723 Introduce thread-like abstraction
Next commits will use it to filter coroutines during stepping IJ-CR-120446 GitOrigin-RevId: 9589c094695181abebc235846cf521358414bf7c
This commit is contained in:
committed by
intellij-monorepo-bot
parent
cd7dc69252
commit
9e5b4cf39d
@@ -31,7 +31,6 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.MessageType;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
@@ -641,8 +640,8 @@ public class DebugProcessEvents extends DebugProcessImpl {
|
||||
// because these evaluations may lead to skipping of more important stepping events,
|
||||
// see IDEA-336282.
|
||||
if (!DebuggerSession.filterBreakpointsDuringSteppingUsingDebuggerEngine()) {
|
||||
ThreadReference filteredThread = getRequestsManager().getFilterThread();
|
||||
if (filteredThread != null && !Comparing.equal(filteredThread, thread)) {
|
||||
LightOrRealThreadInfo filter = getRequestsManager().getFilterThread();
|
||||
if (filter != null && !filter.checkSameThread(thread, suspendContext)) {
|
||||
notifySkippedBreakpoints(event, SkippedBreakpointReason.STEPPING);
|
||||
suspendManager.voteResume(suspendContext);
|
||||
return;
|
||||
|
||||
@@ -879,7 +879,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
DebugProcessImpl debugProcess = context.getDebugProcess();
|
||||
if (resetThreadFilter) {
|
||||
BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(debugProcess.getProject()).getBreakpointManager();
|
||||
breakpointManager.applyThreadFilter(debugProcess, null); // clear the filter on resume
|
||||
breakpointManager.removeThreadFilter(debugProcess); // clear the filter on resume
|
||||
}
|
||||
breakpoint.setSuspendPolicy(
|
||||
context.getSuspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD ? DebuggerSettings.SUSPEND_THREAD : DebuggerSettings.SUSPEND_ALL);
|
||||
@@ -1025,7 +1025,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
|
||||
public void dispose() {
|
||||
Disposer.dispose(myDisposable);
|
||||
myRequestManager.setFilterThread(null);
|
||||
myRequestManager.setThreadFilter(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1681,7 +1681,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
showStatusText(JavaDebuggerBundle.message("status.step.out"));
|
||||
final ThreadReferenceProxyImpl thread = getContextThread();
|
||||
RequestHint hint = getHint(suspendContext, thread, null);
|
||||
applyThreadFilter(thread);
|
||||
applyThreadFilter(getThreadFilterFromContext(suspendContext));
|
||||
startWatchingMethodReturn(thread);
|
||||
step(suspendContext, thread, hint, createCommandToken());
|
||||
super.contextAction(suspendContext);
|
||||
@@ -1731,7 +1731,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
mySession.setIgnoreStepFiltersFlag(getFrameCount(stepThread, suspendContext));
|
||||
}
|
||||
hint.setIgnoreFilters(myForcedIgnoreFilters || mySession.shouldIgnoreSteppingFilters());
|
||||
applyThreadFilter(stepThread);
|
||||
applyThreadFilter(getThreadFilterFromContext(suspendContext));
|
||||
if (myBreakpoint != null) {
|
||||
prepareAndSetSteppingBreakpoint(suspendContext, myBreakpoint, hint, false);
|
||||
}
|
||||
@@ -1813,7 +1813,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
|
||||
RequestHint hint = getHint(suspendContext, stepThread, null);
|
||||
|
||||
applyThreadFilter(stepThread);
|
||||
applyThreadFilter(getThreadFilterFromContext(suspendContext));
|
||||
|
||||
startWatchingMethodReturn(stepThread);
|
||||
|
||||
@@ -1852,7 +1852,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
if (myIgnoreBreakpoints) {
|
||||
DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().disableBreakpoints(DebugProcessImpl.this);
|
||||
}
|
||||
applyThreadFilter(getContextThread());
|
||||
applyThreadFilter(getThreadFilterFromContext(context));
|
||||
prepareAndSetSteppingBreakpoint(context, myRunToCursorBreakpoint, null, false);
|
||||
final DebugProcessImpl debugProcess = context.getDebugProcess();
|
||||
|
||||
@@ -1944,14 +1944,19 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
return myContextThread;
|
||||
}
|
||||
|
||||
protected void applyThreadFilter(ThreadReferenceProxy thread) {
|
||||
@Nullable
|
||||
public LightOrRealThreadInfo getThreadFilterFromContext(@NotNull SuspendContextImpl suspendContext) {
|
||||
return myContextThread != null ? new RealThreadInfo(myContextThread.getThreadReference()) : null;
|
||||
}
|
||||
|
||||
protected void applyThreadFilter(@Nullable LightOrRealThreadInfo threadInfo) {
|
||||
if (getSuspendContext().getSuspendPolicy() == EventRequest.SUSPEND_ALL) {
|
||||
// there could be explicit resume as a result of call to voteSuspend()
|
||||
// e.g. when breakpoint was considered invalid, in that case the filter will be applied _after_
|
||||
// resuming and all breakpoints in other threads will be ignored.
|
||||
// As resume() implicitly cleares the filter, the filter must be always applied _before_ any resume() action happens
|
||||
final BreakpointManager breakpointManager = DebuggerManagerEx.getInstanceEx(getProject()).getBreakpointManager();
|
||||
breakpointManager.applyThreadFilter(DebugProcessImpl.this, thread.getThreadReference());
|
||||
breakpointManager.applyThreadFilter(DebugProcessImpl.this, threadInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2360,7 +2365,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
|
||||
return new ResumeCommand(suspendContext) {
|
||||
@Override
|
||||
public void contextAction(@NotNull SuspendContextImpl suspendContext) {
|
||||
breakpointManager.applyThreadFilter(DebugProcessImpl.this, null); // clear the filter on resume
|
||||
breakpointManager.removeThreadFilter(DebugProcessImpl.this); // clear the filter on resume
|
||||
if (myReturnValueWatcher != null) {
|
||||
myReturnValueWatcher.clear();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.debugger.engine
|
||||
|
||||
import com.sun.jdi.ThreadReference
|
||||
|
||||
interface LightOrRealThreadInfo {
|
||||
val realThread: ThreadReference?
|
||||
|
||||
fun checkSameThread(thread: ThreadReference, suspendContext: SuspendContextImpl): Boolean
|
||||
}
|
||||
|
||||
data class RealThreadInfo(override val realThread: ThreadReference) : LightOrRealThreadInfo {
|
||||
override fun checkSameThread(thread: ThreadReference, suspendContext: SuspendContextImpl): Boolean {
|
||||
return realThread == thread
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class RequestManagerImpl extends DebugProcessAdapterImpl implements Reque
|
||||
* It specifies the thread performing suspend-all stepping.
|
||||
* All events in other threads are ignored.
|
||||
*/
|
||||
private @Nullable ThreadReference myFilterThread;
|
||||
private @Nullable LightOrRealThreadInfo myFilterThread;
|
||||
|
||||
public RequestManagerImpl(DebugProcessImpl debugProcess) {
|
||||
myDebugProcess = debugProcess;
|
||||
@@ -59,12 +59,27 @@ public class RequestManagerImpl extends DebugProcessAdapterImpl implements Reque
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ThreadReference getFilterThread() {
|
||||
public LightOrRealThreadInfo getFilterThread() {
|
||||
return myFilterThread;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ThreadReference getFilterRealThread() {
|
||||
return myFilterThread != null ? myFilterThread.getRealThread() : null;
|
||||
}
|
||||
|
||||
/** @deprecated Use setThreadFilter instead */
|
||||
@Deprecated
|
||||
public void setFilterThread(@Nullable final ThreadReference filterThread) {
|
||||
myFilterThread = filterThread;
|
||||
if (filterThread != null) {
|
||||
setThreadFilter(new RealThreadInfo(filterThread));
|
||||
}
|
||||
else {
|
||||
setThreadFilter(null);
|
||||
}
|
||||
}
|
||||
public void setThreadFilter(@Nullable final LightOrRealThreadInfo filter) {
|
||||
myFilterThread = filter;
|
||||
}
|
||||
|
||||
public Set<EventRequest> findRequests(Requestor requestor) {
|
||||
@@ -352,7 +367,7 @@ public class RequestManagerImpl extends DebugProcessAdapterImpl implements Reque
|
||||
DebuggerManagerThreadImpl.assertIsManagerThread();
|
||||
LOG.assertTrue(findRequestor(request) != null);
|
||||
try {
|
||||
final ThreadReference filterThread = myFilterThread;
|
||||
final ThreadReference filterThread = myFilterThread == null ? null : myFilterThread.getRealThread();
|
||||
if (filterThread != null && DebuggerSession.filterBreakpointsDuringSteppingUsingDebuggerEngine()) {
|
||||
if (request instanceof BreakpointRequest) {
|
||||
((BreakpointRequest)request).addThreadFilter(filterThread);
|
||||
|
||||
@@ -708,8 +708,8 @@ public final class DebuggerSession implements AbstractDebuggerSession {
|
||||
clearSteppingThrough();
|
||||
}
|
||||
DebugProcessImpl debugProcess = (DebugProcessImpl)proc;
|
||||
if (debugProcess.getRequestsManager().getFilterThread() == thread) {
|
||||
DebuggerManagerEx.getInstanceEx(proc.getProject()).getBreakpointManager().applyThreadFilter(debugProcess, null);
|
||||
if (debugProcess.getRequestsManager().getFilterRealThread() == thread) {
|
||||
DebuggerManagerEx.getInstanceEx(proc.getProject()).getBreakpointManager().removeThreadFilter(debugProcess);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ import com.intellij.debugger.DebuggerInvocationUtil;
|
||||
import com.intellij.debugger.JavaDebuggerBundle;
|
||||
import com.intellij.debugger.engine.BreakpointStepMethodFilter;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.LightOrRealThreadInfo;
|
||||
import com.intellij.debugger.engine.RealThreadInfo;
|
||||
import com.intellij.debugger.engine.requests.RequestManagerImpl;
|
||||
import com.intellij.debugger.impl.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -560,19 +562,36 @@ public class BreakpointManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** @deprecated Use removeThreadFilter or version with LightOrRealThreadInfo parameter */
|
||||
@Deprecated
|
||||
public void applyThreadFilter(@NotNull final DebugProcessImpl debugProcess, @Nullable ThreadReference newFilterThread) {
|
||||
if (newFilterThread != null) {
|
||||
applyThreadFilter(debugProcess, new RealThreadInfo(newFilterThread));
|
||||
}
|
||||
else {
|
||||
removeThreadFilter(debugProcess);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeThreadFilter(@NotNull final DebugProcessImpl debugProcess) {
|
||||
applyThreadFilter(debugProcess, (LightOrRealThreadInfo)null);
|
||||
}
|
||||
|
||||
public void applyThreadFilter(@NotNull final DebugProcessImpl debugProcess, @Nullable LightOrRealThreadInfo filter) {
|
||||
final RequestManagerImpl requestManager = debugProcess.getRequestsManager();
|
||||
final ThreadReference oldFilterThread = requestManager.getFilterThread();
|
||||
if (Comparing.equal(newFilterThread, oldFilterThread)) {
|
||||
if (Comparing.equal(filter, requestManager.getFilterThread())) {
|
||||
// the filter already added
|
||||
return;
|
||||
}
|
||||
requestManager.setFilterThread(newFilterThread);
|
||||
requestManager.setThreadFilter(filter);
|
||||
|
||||
if (!DebuggerSession.filterBreakpointsDuringSteppingUsingDebuggerEngine()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ThreadReference newFilterThread = filter == null ? null : filter.getRealThread();
|
||||
final ThreadReference oldFilterThread = requestManager.getFilterRealThread();
|
||||
|
||||
EventRequestManager eventRequestManager = requestManager.getVMRequestManager();
|
||||
if (DebuggerUtilsAsync.isAsyncEnabled() && eventRequestManager instanceof EventRequestManagerImpl) {
|
||||
Stream<EventRequestManagerImpl.ThreadVisibleEventRequestImpl> requests =
|
||||
|
||||
@@ -41,6 +41,6 @@ abstract class AbstractCoroutineBreakpointFacility {
|
||||
// TODO this is nasty. Find a way to apply an empty thread filter only to the newly created breakpoint
|
||||
// TODO consider moving this filtering to event loop?
|
||||
val breakpointManager = DebuggerManagerEx.getInstanceEx(debugProcess.project).breakpointManager
|
||||
breakpointManager.applyThreadFilter(debugProcess, null)
|
||||
breakpointManager.removeThreadFilter(debugProcess)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user