[debugger] do not collect async stack trace when gathering helper exception stack trace

GitOrigin-RevId: 6e0d8b946f3a7799a97ee2a3366339b63ccc49d2
This commit is contained in:
Egor Ushakov
2024-12-13 19:48:05 +00:00
committed by intellij-monorepo-bot
parent 01000a8d10
commit a7a97cceb8
4 changed files with 37 additions and 32 deletions
@@ -14,7 +14,6 @@ import com.intellij.openapi.diagnostic.Attachment
import com.intellij.openapi.diagnostic.RuntimeExceptionWithAttachments
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.util.registry.Registry
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.CommonClassNames
import com.intellij.rt.debugger.MethodInvoker
import com.intellij.util.BitUtil.isSet
@@ -23,22 +22,22 @@ import com.sun.jdi.ObjectReference.INVOKE_NONVIRTUAL
object MethodInvokeUtils {
fun getHelperExceptionStackTrace(evaluationContext: EvaluationContextImpl, e: Exception): String? {
e as? EvaluateException ?: return null
if (e !is EvaluateException) return null
val exceptionFromTargetVM = e.exceptionFromTargetVM ?: return null
var exceptionStack = DebuggerUtilsImpl.getExceptionText(evaluationContext, exceptionFromTargetVM)
if (!exceptionStack.isNullOrEmpty()) {
// drop user frames
val currentStackDepth = DebugProcessImpl.getEvaluationThread(evaluationContext).frameCount()
val lines = StringUtil.splitByLines(exceptionStack) // exclude empty lines
if (lines.size > currentStackDepth) {
return lines.asSequence().take(lines.size - currentStackDepth).joinToString(separator = "\n")
}
else {
logger<MethodInvokeUtils>().error("Invalid helper stack (expected currentStackDepth = ${currentStackDepth}) : ${exceptionStack}")
return exceptionStack
}
val stackTraceArray = DebuggerUtilsImpl.invokeThrowableGetStackTrace(exceptionFromTargetVM, evaluationContext, true)
if (stackTraceArray !is ArrayReference) return null
val values = stackTraceArray.values
if (values.isEmpty()) return null
// drop user frames
val currentStackDepth = DebugProcessImpl.getEvaluationThread(evaluationContext).frameCount()
val keepLines = if (values.size <= currentStackDepth) values.size else values.size - currentStackDepth
val stackTraceString =
DebuggerUtils.getValueAsString(evaluationContext, exceptionFromTargetVM) + "\n" +
values.asSequence().take(keepLines).map { DebuggerUtils.getValueAsString(evaluationContext, it) }.joinToString(prefix = "\tat ", separator = "\n")
if (values.size <= currentStackDepth) {
logger<MethodInvokeUtils>().error("Invalid helper stack (expected currentStackDepth = ${currentStackDepth}) : ${stackTraceString}")
}
return null
return stackTraceString
}
}
@@ -544,4 +544,18 @@ public final class DebuggerUtilsImpl extends DebuggerUtilsEx {
Collections.singletonList(exceptionObject));
return value != null ? ((StringReference)value).value() : null;
}
@Nullable
public static Value invokeThrowableGetStackTrace(@NotNull ObjectReference exceptionObj,
@NotNull EvaluationContextImpl evaluationContext,
boolean keepResult) throws EvaluateException {
if (instanceOf(exceptionObj.type(), "java.lang.Throwable")) {
Method method = findMethod(exceptionObj.referenceType(), "getStackTrace", "()[Ljava/lang/StackTraceElement;");
DebugProcessImpl debugProcess = evaluationContext.getDebugProcess();
ThrowableComputable<Value, EvaluateException> invoker = () -> debugProcess.invokeInstanceMethod(
evaluationContext, exceptionObj, Objects.requireNonNull(method), Collections.emptyList(), 0, true);
return keepResult ? evaluationContext.computeAndKeep(invoker) : invoker.compute();
}
return null;
}
}
@@ -12,6 +12,7 @@ import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsImpl;
import com.intellij.debugger.impl.PositionUtil;
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.settings.ViewsGeneralSettings;
@@ -129,7 +130,7 @@ public class FieldDescriptorImpl extends ValueDescriptorImpl implements FieldDes
((ArrayReference)value).length() == 0 &&
DebuggerUtils.instanceOf(myObject.type(), CommonClassNames.JAVA_LANG_THROWABLE)) {
try {
invokeExceptionGetStackTrace(myObject, evaluationContext);
DebuggerUtilsImpl.invokeThrowableGetStackTrace(myObject, evaluationContext, false);
return true;
}
catch (Throwable e) {
@@ -4,7 +4,10 @@ package com.intellij.debugger.ui.impl.watch;
import com.intellij.Patches;
import com.intellij.debugger.DebuggerContext;
import com.intellij.debugger.JavaDebuggerBundle;
import com.intellij.debugger.engine.*;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.DebuggerManagerThreadImpl;
import com.intellij.debugger.engine.JavaValue;
import com.intellij.debugger.engine.SuspendContextImpl;
import com.intellij.debugger.engine.evaluation.CodeFragmentFactoryContextWrapper;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
@@ -19,8 +22,8 @@ import com.intellij.debugger.ui.tree.DebuggerTreeNode;
import com.intellij.debugger.ui.tree.NodeDescriptor;
import com.intellij.debugger.ui.tree.NodeDescriptorNameAdjuster;
import com.intellij.debugger.ui.tree.ValueDescriptor;
import com.intellij.debugger.ui.tree.render.Renderer;
import com.intellij.debugger.ui.tree.render.*;
import com.intellij.debugger.ui.tree.render.Renderer;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
@@ -46,7 +49,6 @@ import org.jetbrains.concurrency.Promise;
import org.jetbrains.concurrency.Promises;
import javax.swing.*;
import java.util.Collections;
import java.util.Objects;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
@@ -263,17 +265,6 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
return myInitFuture;
}
@Nullable
protected static Value invokeExceptionGetStackTrace(ObjectReference exceptionObj, EvaluationContextImpl evaluationContext)
throws EvaluateException {
Method method = DebuggerUtils.findMethod(exceptionObj.referenceType(), "getStackTrace", "()[Ljava/lang/StackTraceElement;");
if (method != null) {
return evaluationContext.getDebugProcess().invokeInstanceMethod(
evaluationContext, exceptionObj, method, Collections.emptyList(), 0, true);
}
return null;
}
@Nullable
private static ObjectReference getTargetExceptionWithStackTraceFilled(@Nullable EvaluationContextImpl evaluationContext,
EvaluateException ex,
@@ -281,10 +272,10 @@ public abstract class ValueDescriptorImpl extends NodeDescriptorImpl implements
final ObjectReference exceptionObj = ex.getExceptionFromTargetVM();
if (exceptionObj != null && evaluationContext != null) {
try {
Value trace = invokeExceptionGetStackTrace(exceptionObj, evaluationContext);
Value trace = DebuggerUtilsImpl.invokeThrowableGetStackTrace(exceptionObj, evaluationContext, false);
// print to console as well
if (printToConsole && trace instanceof ArrayReference) {
if (printToConsole && trace != null) {
evaluationContext.getDebugProcess().printToConsole(DebuggerUtilsImpl.getExceptionText(evaluationContext, exceptionObj));
}
}