fixed: 1. no stackframes for threads on first pause; 2. pause and then step - locks debugger

This commit is contained in:
Eugene Zhuravlev
2005-01-26 12:43:41 +03:00
parent f5a4ffbb56
commit d447cb36ef
13 changed files with 113 additions and 55 deletions
@@ -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());
}