mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fixed: 1. no stackframes for threads on first pause; 2. pause and then step - locks debugger
This commit is contained in:
@@ -3,8 +3,10 @@ package com.intellij.debugger.actions;
|
||||
import com.intellij.debugger.DebuggerManager;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataConstants;
|
||||
@@ -27,7 +29,11 @@ public class ForceStepIntoAction extends AnAction {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
DebuggerSession debuggerSession = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession();
|
||||
presentation.setEnabled(debuggerSession != null && debuggerSession.isPaused());
|
||||
final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
DebuggerSession debuggerSession = context.getDebuggerSession();
|
||||
final boolean isPaused = debuggerSession != null && debuggerSession.isPaused();
|
||||
final SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null;
|
||||
presentation.setEnabled(isPaused && hasCurrentThread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@ import com.intellij.openapi.actionSystem.Presentation;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
|
||||
/*
|
||||
* Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
|
||||
@@ -30,8 +32,12 @@ public class ForceStepOverAction extends AnAction {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
DebuggerSession debuggerSession = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession();
|
||||
presentation.setEnabled(debuggerSession != null && debuggerSession.isPaused());
|
||||
final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
DebuggerSession debuggerSession = context.getDebuggerSession();
|
||||
final boolean isPaused = debuggerSession != null && debuggerSession.isPaused();
|
||||
final SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null;
|
||||
presentation.setEnabled(isPaused && hasCurrentThread);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.intellij.debugger.actions;
|
||||
import com.intellij.debugger.DebuggerManager;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataConstants;
|
||||
@@ -26,7 +28,11 @@ public class StepIntoAction extends AnAction {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
DebuggerSession debuggerSession = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession();
|
||||
presentation.setEnabled(debuggerSession != null && debuggerSession.isPaused());
|
||||
final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
DebuggerSession debuggerSession = context.getDebuggerSession();
|
||||
final boolean isPaused = debuggerSession != null && debuggerSession.isPaused();
|
||||
final SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null;
|
||||
presentation.setEnabled(isPaused && hasCurrentThread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@ package com.intellij.debugger.actions;
|
||||
import com.intellij.debugger.DebuggerManager;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataConstants;
|
||||
@@ -27,7 +29,11 @@ public class StepOutAction extends AnAction {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
DebuggerSession debuggerSession = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession();
|
||||
presentation.setEnabled(debuggerSession != null && debuggerSession.isPaused());
|
||||
final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
DebuggerSession debuggerSession = context.getDebuggerSession();
|
||||
final boolean isPaused = debuggerSession != null && debuggerSession.isPaused();
|
||||
final SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null;
|
||||
presentation.setEnabled(isPaused && hasCurrentThread);
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,10 @@ package com.intellij.debugger.actions;
|
||||
|
||||
import com.intellij.debugger.DebuggerManager;
|
||||
import com.intellij.debugger.DebuggerManagerEx;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerSession;
|
||||
import com.intellij.debugger.impl.DebuggerContextImpl;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DataConstants;
|
||||
@@ -27,7 +29,11 @@ public class StepOverAction extends AnAction {
|
||||
presentation.setEnabled(false);
|
||||
return;
|
||||
}
|
||||
DebuggerSession debuggerSession = (DebuggerManagerEx.getInstanceEx(project)).getContext().getDebuggerSession();
|
||||
presentation.setEnabled(debuggerSession != null && debuggerSession.isPaused());
|
||||
final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(project)).getContext();
|
||||
DebuggerSession debuggerSession = context.getDebuggerSession();
|
||||
final boolean isPaused = debuggerSession != null && debuggerSession.isPaused();
|
||||
final SuspendContextImpl suspendContext = context.getSuspendContext();
|
||||
final boolean hasCurrentThread = suspendContext != null && suspendContext.getThread() != null;
|
||||
presentation.setEnabled(isPaused && hasCurrentThread);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ public class DebugProcessEvents extends DebugProcessImpl {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("STEPOUT doStep");
|
||||
}
|
||||
shouldResume = doStep(suspendContext, hint.getDepth(), hint);
|
||||
shouldResume = doStep(suspendContext.getThread(), hint.getDepth(), hint);
|
||||
}
|
||||
|
||||
if(!shouldResume && hint.isRestoreBreakpoints()) {
|
||||
|
||||
@@ -212,18 +212,20 @@ public abstract class DebugProcessImpl implements DebugProcess {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param suspendContext
|
||||
* @return
|
||||
* @param stepThread
|
||||
* @param depth
|
||||
* @param hint may be null
|
||||
* @return
|
||||
*/
|
||||
protected boolean doStep(SuspendContextImpl suspendContext, int depth, RequestHint hint) {
|
||||
final ThreadReferenceProxyImpl currentThreadProxy = suspendContext.getThread();
|
||||
if (currentThreadProxy == null || !currentThreadProxy.isSuspended()) return false;
|
||||
protected boolean doStep(ThreadReferenceProxyImpl stepThread, int depth, RequestHint hint) {
|
||||
final ThreadReferenceProxyImpl currentThreadProxy = stepThread;
|
||||
if (currentThreadProxy == null || !currentThreadProxy.isSuspended()) {
|
||||
return false;
|
||||
}
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("DO_STEP: creating step request for " + currentThreadProxy.getThreadReference());
|
||||
}
|
||||
deleteStepRequests(suspendContext.getThread());
|
||||
deleteStepRequests(currentThreadProxy);
|
||||
EventRequestManager requestManager = getVirtualMachineProxy().eventRequestManager();
|
||||
StepRequest stepRequest = requestManager.createStepRequest(currentThreadProxy.getThreadReference(), StepRequest.STEP_LINE, depth);
|
||||
DebuggerSettings settings = DebuggerSettings.getInstance();
|
||||
@@ -264,7 +266,7 @@ public abstract class DebugProcessImpl implements DebugProcess {
|
||||
// [jeka] on attempt to delete a request assigned to a thread with unknown status, a JDWP error occures
|
||||
continue;
|
||||
}
|
||||
else if(threadReference.equals(requestsInThread.getThreadReference())) {
|
||||
else /*if(threadReference.equals(requestsInThread.getThreadReference())) */{
|
||||
toDelete.add(request);
|
||||
}
|
||||
}
|
||||
@@ -1153,9 +1155,9 @@ public abstract class DebugProcessImpl implements DebugProcess {
|
||||
|
||||
public void contextAction() {
|
||||
showStatusText("Stepping out");
|
||||
if (doStep(getSuspendContext(), StepRequest.STEP_OUT, null)) {
|
||||
super.contextAction();
|
||||
}
|
||||
final SuspendContextImpl suspendContext = getSuspendContext();
|
||||
doStep(suspendContext.getThread(), StepRequest.STEP_OUT, null);
|
||||
super.contextAction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1169,11 +1171,11 @@ public abstract class DebugProcessImpl implements DebugProcess {
|
||||
|
||||
public void contextAction() {
|
||||
showStatusText("Stepping into");
|
||||
RequestHint hint = new RequestHint(getSuspendContext(), StepRequest.STEP_INTO);
|
||||
final SuspendContextImpl suspendContext = getSuspendContext();
|
||||
RequestHint hint = new RequestHint(suspendContext, StepRequest.STEP_INTO);
|
||||
hint.setIgnoreFilters(myIgnoreFilters);
|
||||
if (doStep(getSuspendContext(), StepRequest.STEP_INTO, hint)) {
|
||||
super.contextAction();
|
||||
}
|
||||
doStep(suspendContext.getThread(), StepRequest.STEP_INTO, hint);
|
||||
super.contextAction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1187,15 +1189,17 @@ public abstract class DebugProcessImpl implements DebugProcess {
|
||||
|
||||
public void contextAction() {
|
||||
showStatusText("Stepping over");
|
||||
RequestHint hint = new RequestHint(getSuspendContext(), StepRequest.STEP_OVER);
|
||||
final SuspendContextImpl suspendContext = getSuspendContext();
|
||||
RequestHint hint = new RequestHint(suspendContext, StepRequest.STEP_OVER);
|
||||
hint.setRestoreBreakpoints(myIsIgnoreBreakpoints);
|
||||
|
||||
if (doStep(getSuspendContext(), StepRequest.STEP_OVER, hint)) {
|
||||
final boolean succeeded = doStep(suspendContext.getThread(), StepRequest.STEP_OVER, hint);
|
||||
if (succeeded) {
|
||||
if (myIsIgnoreBreakpoints) {
|
||||
DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().disableBreakpoints(DebugProcessImpl.this);
|
||||
}
|
||||
super.contextAction();
|
||||
}
|
||||
super.contextAction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1244,7 +1248,7 @@ public abstract class DebugProcessImpl implements DebugProcess {
|
||||
getVirtualMachineProxy().suspend();
|
||||
logThreads();
|
||||
SuspendContextImpl suspendContext = mySuspendManager.pushSuspendContext(EventRequest.SUSPEND_ALL, 0);
|
||||
mySuspendManager.notifyPaused(suspendContext);
|
||||
myDebugProcessDispatcher.getMulticaster().paused(suspendContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.util.ProgressIndicatorListenerAdapter;
|
||||
import com.intellij.openapi.progress.util.ProgressWindowWithNotification;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.sun.jdi.VMDisconnectedException;
|
||||
|
||||
@@ -47,17 +48,17 @@ public class DebuggerManagerThreadImpl extends InvokeAndWaitThread<DebuggerComma
|
||||
}
|
||||
|
||||
public void invokeAndWait(DebuggerCommandImpl managerCommand, int priority) {
|
||||
LOG.assertTrue(!SwingUtilities.isEventDispatchThread());
|
||||
LOG.assertTrue(!ApplicationManager.getApplication().isDispatchThread());
|
||||
LOG.assertTrue(!(currentThread() instanceof DebuggerManagerThreadImpl),
|
||||
"Should be invoked outside manager thread, use DebuggerManagerThreadImpl.getInstance(..).invoke...");
|
||||
super.invokeAndWait(managerCommand, priority); //To change body of overridden methods use File | Settings | File Templates.
|
||||
super.invokeAndWait(managerCommand, priority);
|
||||
}
|
||||
|
||||
public void invokeAndWait(DebuggerCommandImpl managerCommand) {
|
||||
LOG.assertTrue(!SwingUtilities.isEventDispatchThread());
|
||||
LOG.assertTrue(!ApplicationManager.getApplication().isDispatchThread());
|
||||
LOG.assertTrue(!(currentThread() instanceof DebuggerManagerThreadImpl),
|
||||
"Should be invoked outside manager thread, use DebuggerManagerThreadImpl.getInstance(..).invoke...");
|
||||
invokeAndWait(managerCommand, NORMAL_PRIORITY);
|
||||
super.invokeAndWait(managerCommand, NORMAL_PRIORITY);
|
||||
}
|
||||
|
||||
public void invoke(DebuggerCommandImpl managerCommand) {
|
||||
|
||||
@@ -21,6 +21,8 @@ public class SuspendManagerImpl implements SuspendManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.engine.SuspendManager");
|
||||
|
||||
private final LinkedList<SuspendContextImpl> myEventContexts = new LinkedList<SuspendContextImpl>();
|
||||
// contexts, paused at breakpoint or another debugger event requests. Note that thread, explicitly paused by user is not considered as
|
||||
// "paused at breakpoint" and JDI prohibits data queries on its stackframes
|
||||
private final LinkedList<SuspendContextImpl> myPausedContexts = new LinkedList<SuspendContextImpl>();
|
||||
private final Set<ThreadReferenceProxyImpl> myFrozenThreads = new HashSet<ThreadReferenceProxyImpl>();
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.sun.jdi.request.EventRequest;
|
||||
import com.sun.jdi.ThreadReference;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
@@ -170,9 +171,24 @@ public class DebuggerSession {
|
||||
}
|
||||
|
||||
if(currentThread == null) {
|
||||
currentThread = getProcess().getVirtualMachineProxy().allThreads().iterator().next();
|
||||
final Iterator<ThreadReferenceProxyImpl> iterator = getProcess().getVirtualMachineProxy().allThreads().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
currentThread = iterator.next();
|
||||
if (currentThread.status() == ThreadReference.THREAD_STATUS_RUNNING) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (!currentThread.isSuspended()) {
|
||||
// wait until thread is considered suspended. Querying data from a thread immediately after VM.suspend()
|
||||
// may result in IncompatibleThreadStateException, most likely some time after suspend() VM erroneously thinks that thread is still running
|
||||
try {
|
||||
Thread.sleep(10);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
|
||||
StackFrameProxyImpl proxy;
|
||||
try {
|
||||
@@ -370,18 +386,21 @@ public class DebuggerSession {
|
||||
}
|
||||
|
||||
public void stepOut() {
|
||||
mySteppingThroughThreads.add(getSuspendContext().getThread());
|
||||
resumeAction(myDebugProcess.createStepOutCommand(getSuspendContext()), EVENT_STEP);
|
||||
final SuspendContextImpl suspendContext = getSuspendContext();
|
||||
mySteppingThroughThreads.add(suspendContext.getThread());
|
||||
resumeAction(myDebugProcess.createStepOutCommand(suspendContext), EVENT_STEP);
|
||||
}
|
||||
|
||||
public void stepOver(boolean ignoreBreakpoints) {
|
||||
mySteppingThroughThreads.add(getSuspendContext().getThread());
|
||||
resumeAction(myDebugProcess.createStepOverCommand(getSuspendContext(), ignoreBreakpoints), EVENT_STEP);
|
||||
final SuspendContextImpl suspendContext = getSuspendContext();
|
||||
mySteppingThroughThreads.add(suspendContext.getThread());
|
||||
resumeAction(myDebugProcess.createStepOverCommand(suspendContext, ignoreBreakpoints), EVENT_STEP);
|
||||
}
|
||||
|
||||
public void stepInto(final boolean ignoreFilters) {
|
||||
mySteppingThroughThreads.add(getSuspendContext().getThread());
|
||||
resumeAction(myDebugProcess.createStepIntoCommand(getSuspendContext(), ignoreFilters), EVENT_STEP);
|
||||
final SuspendContextImpl suspendContext = getSuspendContext();
|
||||
mySteppingThroughThreads.add(suspendContext.getThread());
|
||||
resumeAction(myDebugProcess.createStepIntoCommand(suspendContext, ignoreFilters), EVENT_STEP);
|
||||
}
|
||||
|
||||
public void runToCursor(Document document, int line) {
|
||||
|
||||
@@ -9,21 +9,25 @@ import com.intellij.util.concurrency.Semaphore;
|
||||
* Time: 12:56:52 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
public abstract class InvokeAndWaitEventImpl implements InvokeAndWaitEvent{
|
||||
private Semaphore myInvokeAndWaitSemaphore;
|
||||
public abstract class InvokeAndWaitEventImpl extends Semaphore implements InvokeAndWaitEvent{
|
||||
|
||||
public final void release() {
|
||||
if(myInvokeAndWaitSemaphore != null) myInvokeAndWaitSemaphore.up();
|
||||
up();
|
||||
}
|
||||
|
||||
public final void hold() {
|
||||
if(myInvokeAndWaitSemaphore == null) {
|
||||
myInvokeAndWaitSemaphore = new Semaphore();
|
||||
}
|
||||
myInvokeAndWaitSemaphore.down();
|
||||
down();
|
||||
}
|
||||
|
||||
public void waitFor() {
|
||||
myInvokeAndWaitSemaphore.waitFor();
|
||||
public final void down() {
|
||||
super.down();
|
||||
}
|
||||
|
||||
public final void up() {
|
||||
super.up();
|
||||
}
|
||||
|
||||
public final void waitFor() {
|
||||
super.waitFor();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,10 +23,9 @@ public final class ThreadReferenceProxyImpl extends ObjectReferenceProxyImpl imp
|
||||
private String myName;
|
||||
private int myFrameCount = -1;
|
||||
// stackframes, 0 - bottom
|
||||
private List<StackFrameProxyImpl> myFramesFromBottom = new ArrayList<StackFrameProxyImpl>();
|
||||
//cache build on the base of myFramesFromBottom
|
||||
//0 - top
|
||||
private List<StackFrameProxyImpl> myFrames = new ArrayList<StackFrameProxyImpl>();
|
||||
private List<StackFrameProxyImpl> myFramesFromBottom = new ArrayList<StackFrameProxyImpl>();
|
||||
//cache build on the base of myFramesFromBottom 0 - top, initially nothing is cached
|
||||
private List<StackFrameProxyImpl> myFrames = null;
|
||||
|
||||
private ThreadGroupReferenceProxyImpl myThreadGroupProxy;
|
||||
|
||||
|
||||
@@ -90,9 +90,8 @@ public class ThreadDescriptorImpl extends NodeDescriptorImpl implements ThreadDe
|
||||
SuspendManager suspendManager = context.getDebugProcess().getSuspendManager();
|
||||
myIsSuspended = suspendManager.isSuspended(thread);
|
||||
myIsExpandable = calcExpandable(suspendManager);
|
||||
SuspendContextImpl threadContext = SuspendManagerUtil.findContextByThread(suspendManager, thread);
|
||||
mySuspendContext = SuspendManagerUtil.getSuspendContextForThread(context.getSuspendContext(), thread);
|
||||
myIsAtBreakpoint = threadContext != null;
|
||||
myIsAtBreakpoint = SuspendManagerUtil.findContextByThread(suspendManager, thread) != null;
|
||||
myIsCurrent = calcIsCurrent(context);
|
||||
myIsFrozen = suspendManager.isFrozen(getThreadReference());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user