Browse Source

Yet again significantly rewriting process state control

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3136 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 17 years ago
parent
commit
8759a05e66
  1. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs
  2. 108
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs
  3. 7
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process.cs
  4. 11
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/StackFrame.cs
  5. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs
  6. 38
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs
  7. 3
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Breakpoint.cs

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs

@ -126,7 +126,7 @@ namespace Debugger
} }
process.NotifyEvaluationStarted(newEval); process.NotifyEvaluationStarted(newEval);
process.AsyncContinue_KeepDebuggeeState(); process.AsyncContinue(DebuggeeStateAction.Keep);
return newEval; return newEval;
} }

108
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs

@ -10,6 +10,8 @@ using System.Threading;
namespace Debugger namespace Debugger
{ {
internal enum DebuggeeStateAction { Keep, Clear }
public partial class Process public partial class Process
{ {
// Order: // Order:
@ -26,6 +28,8 @@ namespace Debugger
public virtual void OnPaused() public virtual void OnPaused()
{ {
AssertPaused(); AssertPaused();
// No real purpose
if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback.");
TraceMessage ("Debugger event: OnPaused()"); TraceMessage ("Debugger event: OnPaused()");
if (Paused != null) { if (Paused != null) {
foreach(Delegate d in Paused.GetInvocationList()) { foreach(Delegate d in Paused.GetInvocationList()) {
@ -41,6 +45,8 @@ namespace Debugger
protected virtual void OnResumed() protected virtual void OnResumed()
{ {
AssertRunning(); AssertRunning();
// No real purpose
if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback.");
TraceMessage ("Debugger event: OnResumed()"); TraceMessage ("Debugger event: OnResumed()");
if (Resumed != null) { if (Resumed != null) {
Resumed(this, new ProcessEventArgs(this)); Resumed(this, new ProcessEventArgs(this));
@ -50,9 +56,10 @@ namespace Debugger
#endregion #endregion
#region PauseSession #region PauseSession & DebugeeState
PauseSession pauseSession; PauseSession pauseSession;
DebuggeeState debuggeeState;
/// <summary> /// <summary>
/// Indentification of the current debugger session. This value changes whenever debugger is continued /// Indentification of the current debugger session. This value changes whenever debugger is continued
@ -63,30 +70,6 @@ namespace Debugger
} }
} }
internal void CreatePauseSession(PausedReason pauseReason)
{
if (pauseSession != null) {
throw new DebuggerException("Pause session already created");
}
pauseSession = new PauseSession(pauseReason);
}
internal void ExpirePauseSession()
{
if (pauseSession == null) {
throw new DebuggerException("Pause session already expired");
}
PauseSession oldPauseSession = pauseSession;
pauseSession = null;
oldPauseSession.NotifyHasExpired();
}
#endregion
#region DebugeeState
DebuggeeState debuggeeState;
/// <summary> /// <summary>
/// Indentification of the state of the debugee. This value changes whenever the state of the debugee significatntly changes /// Indentification of the state of the debugee. This value changes whenever the state of the debugee significatntly changes
/// </summary> /// </summary>
@ -96,28 +79,47 @@ namespace Debugger
} }
} }
internal void CreateDebuggeeState() /// <summary> Puts the process into a paused state </summary>
internal void NotifyPaused(PausedReason pauseReason)
{ {
if (debuggeeState != null) { AssertRunning();
throw new DebuggerException("Debugee state already created"); pauseSession = new PauseSession(pauseReason);
if (debuggeeState == null) {
debuggeeState = new DebuggeeState(this);
} }
if (pauseSession == null) { }
throw new DebuggerException("Pause session must exist (update order error)");
/// <summary> Puts the process into a resumed state </summary>
internal void NotifyResumed(DebuggeeStateAction action)
{
AssertPaused();
PauseSession oldPauseSession = pauseSession;
pauseSession = null;
oldPauseSession.NotifyHasExpired();
if (action == DebuggeeStateAction.Clear) {
if (debuggeeState == null) throw new DebuggerException("Debugee state already cleared");
DebuggeeState oldDebugeeState = debuggeeState;
debuggeeState = null;
oldDebugeeState.NotifyHasExpired();
} }
debuggeeState = new DebuggeeState(this);
} }
internal void ExpireDebuggeeState() /// <summary> Sets up the eviroment and raises user events </summary>
internal void RaisePausedEvents()
{ {
if (debuggeeState == null) { DisableAllSteppers();
throw new DebuggerException("Debugee state already expired"); SelectMostRecentStackFrameWithLoadedSymbols();
if (this.PauseSession.PausedReason == PausedReason.Exception) {
ExceptionEventArgs args = new ExceptionEventArgs(this, this.SelectedThread.CurrentException, this.SelectedThread.CurrentExceptionType, this.SelectedThread.CurrentExceptionIsUnhandled);
OnExceptionThrown(args);
// The event could have resumed or killed the process
} }
if (pauseSession != null) {
throw new DebuggerException("Pause session must not exist (update order error)"); if (this.IsPaused && !this.HasExpired) {
OnPaused();
// The event could have resumed the process
} }
DebuggeeState oldDebugeeState = debuggeeState;
debuggeeState = null;
oldDebugeeState.NotifyHasExpired();
} }
#endregion #endregion
@ -179,13 +181,8 @@ namespace Debugger
corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway
CreatePauseSession(PausedReason.ForcedBreak); NotifyPaused(PausedReason.ForcedBreak);
CreateDebuggeeState(); RaisePausedEvents();
SelectMostRecentStackFrameWithLoadedSymbols();
DisableAllSteppers();
OnPaused();
} }
#region Convenience methods #region Convenience methods
@ -200,24 +197,19 @@ namespace Debugger
public void AsyncContinue() public void AsyncContinue()
{ {
AssertPaused(); AsyncContinue(DebuggeeStateAction.Clear);
if (callbackInterface.IsInCallback) {
throw new DebuggerException("Can not continue from within callback.");
}
ExpirePauseSession();
ExpireDebuggeeState();
OnResumed();
corProcess.Continue(0);
} }
internal void AsyncContinue_KeepDebuggeeState() internal void AsyncContinue(DebuggeeStateAction action)
{ {
AssertPaused(); AssertPaused();
ExpirePauseSession(); NotifyResumed(action);
corProcess.Continue(0); corProcess.Continue(0);
if (action == DebuggeeStateAction.Clear) {
OnResumed();
}
} }
/// <summary> Terminates the execution of the process </summary> /// <summary> Terminates the execution of the process </summary>

7
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process.cs

@ -39,11 +39,8 @@ namespace Debugger
Expired(this, new ProcessEventArgs(this)); Expired(this, new ProcessEventArgs(this));
} }
// Expire pause seesion first // Expire pause seesion first
if (PauseSession != null) { if (IsPaused) {
ExpirePauseSession(); NotifyResumed(DebuggeeStateAction.Clear);
}
if (DebuggeeState != null) {
ExpireDebuggeeState();
} }
debugger.RemoveProcess(this); debugger.RemoveProcess(this);
} }

11
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/StackFrame.cs

@ -152,7 +152,7 @@ namespace Debugger
public void AsyncStepOut() public void AsyncStepOut()
{ {
new Stepper(this, "StackFrame step out").StepOut(); new Stepper(this, "StackFrame step out").StepOut();
process.AsyncContinue(); process.AsyncContinue(DebuggeeStateAction.Clear);
} }
void AsyncStep(bool stepIn) void AsyncStep(bool stepIn)
@ -177,7 +177,7 @@ namespace Debugger
new Stepper(this, "StackFrame step over").StepOver(nextSt.StepRanges); new Stepper(this, "StackFrame step over").StepOver(nextSt.StepRanges);
} }
process.AsyncContinue(); process.AsyncContinue(DebuggeeStateAction.Clear);
} }
/// <summary> /// <summary>
@ -314,10 +314,9 @@ namespace Debugger
} else { } else {
// invalidates all frames and chains for the current thread // invalidates all frames and chains for the current thread
CorILFrame.SetIP((uint)ilOffset); CorILFrame.SetIP((uint)ilOffset);
process.ExpirePauseSession(); process.NotifyResumed(DebuggeeStateAction.Keep);
process.CreatePauseSession(PausedReason.SetIP); process.NotifyPaused(PausedReason.SetIP);
process.SelectMostRecentStackFrameWithLoadedSymbols(); process.RaisePausedEvents();
process.OnPaused();
} }
} catch { } catch {
return null; return null;

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs

@ -225,7 +225,7 @@ namespace Debugger
throw; throw;
} }
Process.AsyncContinue_KeepDebuggeeState(); Process.AsyncContinue(DebuggeeStateAction.Keep);
Process.WaitForPause(); Process.WaitForPause();
return true; return true;
} }

38
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs

@ -54,16 +54,16 @@ namespace Debugger
if (process.IsPaused && process.PauseSession.PausedReason == PausedReason.ForcedBreak) { if (process.IsPaused && process.PauseSession.PausedReason == PausedReason.ForcedBreak) {
process.TraceMessage("Processing post-break callback"); process.TraceMessage("Processing post-break callback");
// This compensates for the break call and we are in normal callback handling mode // This compensates for the break call and we are in normal callback handling mode
process.AsyncContinue_KeepDebuggeeState(); process.AsyncContinue(DebuggeeStateAction.Keep);
// Start of call back - create new pause session (as usual) // Start of call back - create new pause session (as usual)
process.CreatePauseSession(pausedReason); process.NotifyPaused(pausedReason);
// Make sure we stay pause after the callback is handled // Make sure we stay pause after the callback is handled
pauseOnNextExit = true; pauseOnNextExit = true;
return; return;
} }
if (process.IsRunning) { if (process.IsRunning) {
process.CreatePauseSession(pausedReason); process.NotifyPaused(pausedReason);
return; return;
} }
@ -90,8 +90,7 @@ namespace Debugger
// Ignore events during property evaluation // Ignore events during property evaluation
if (!pauseOnNextExit || process.Evaluating || hasQueuedCallbacks) { if (!pauseOnNextExit || process.Evaluating || hasQueuedCallbacks) {
process.ExpirePauseSession(); process.AsyncContinue(DebuggeeStateAction.Keep);
process.CorProcess.Continue(0);
} else { } else {
pauseOnNextExit = false; pauseOnNextExit = false;
Pause(); Pause();
@ -102,36 +101,14 @@ namespace Debugger
void Pause() void Pause()
{ {
process.SelectMostRecentStackFrameWithLoadedSymbols();
process.DisableAllSteppers();
if (process.PauseSession.PausedReason == PausedReason.EvalComplete || if (process.PauseSession.PausedReason == PausedReason.EvalComplete ||
process.PauseSession.PausedReason == PausedReason.ExceptionIntercepted) { process.PauseSession.PausedReason == PausedReason.ExceptionIntercepted) {
// Keep debugge state process.SelectMostRecentStackFrameWithLoadedSymbols();
process.DisableAllSteppers();
// Do not raise events // Do not raise events
} else { } else {
process.CreateDebuggeeState();
// Raise the pause event outside the callback // Raise the pause event outside the callback
process.Debugger.MTA2STA.AsyncCall(RaiseEvents); process.Debugger.MTA2STA.AsyncCall(process.RaisePausedEvents);
}
}
void RaiseEvents()
{
if (process.PauseSession.PausedReason == PausedReason.Exception) {
// Needs to be done after the debugge state is created
process.SelectedThread.CurrentException_DebuggeeState = process.DebuggeeState;
}
if (process.PauseSession.PausedReason == PausedReason.Exception) {
ExceptionEventArgs args = new ExceptionEventArgs(process, process.SelectedThread.CurrentException, process.SelectedThread.CurrentExceptionType, process.SelectedThread.CurrentExceptionIsUnhandled);
process.OnExceptionThrown(args);
// The event could have resumed or killed the process
}
if (process.IsPaused && !process.HasExpired) {
process.OnPaused();
// The event could have resumed the process
} }
} }
@ -467,6 +444,7 @@ namespace Debugger
// Exception -> Exception2(pAppDomain, pThread, null, 0, exceptionType, 0); // Exception -> Exception2(pAppDomain, pThread, null, 0, exceptionType, 0);
process.SelectedThread.CurrentException = new Exception(new Value(process, new Expressions.CurrentExceptionExpression(), process.SelectedThread.CorThread.CurrentException)); process.SelectedThread.CurrentException = new Exception(new Value(process, new Expressions.CurrentExceptionExpression(), process.SelectedThread.CorThread.CurrentException));
process.SelectedThread.CurrentException_DebuggeeState = process.DebuggeeState;
process.SelectedThread.CurrentExceptionType = (ExceptionType)exceptionType; process.SelectedThread.CurrentExceptionType = (ExceptionType)exceptionType;
process.SelectedThread.CurrentExceptionIsUnhandled = (ExceptionType)exceptionType == ExceptionType.Unhandled; process.SelectedThread.CurrentExceptionIsUnhandled = (ExceptionType)exceptionType == ExceptionType.Unhandled;

3
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/Breakpoint.cs

@ -23,6 +23,8 @@ namespace Debugger.Tests.TestPrograms
#if TEST_CODE #if TEST_CODE
namespace Debugger.Tests { namespace Debugger.Tests {
using NUnit.Framework;
public partial class DebuggerTests public partial class DebuggerTests
{ {
[NUnit.Framework.Test] [NUnit.Framework.Test]
@ -32,6 +34,7 @@ namespace Debugger.Tests {
StartTest("Breakpoint.cs"); StartTest("Breakpoint.cs");
Assert.IsTrue(breakpoint.HadBeenSet);
ObjectDump(breakpoint); ObjectDump(breakpoint);
process.Continue(); process.Continue();
process.Continue(); process.Continue();

Loading…
Cancel
Save