From ee7edd15b7fef40e5f60604e4f5ec85b5392fd8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Sat, 26 Jan 2008 01:27:29 +0000 Subject: [PATCH] Terminate command does 'Break+Terminate' rather then 'Continue+Break+Terminate'. I think this was left over from .NET 1.1 hack. Changed the way callbacks are handled - it uses pauseOnNextExit flag now rather then two different exit procedures. Queued callback are drained from the process queue. git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2921 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Project/Debugger.Core.csproj | 1 + .../Src/Control/Process-StateControl.cs | 10 +- .../Project/Src/Internal/ManagedCallback.cs | 133 +++++++++--------- .../Src/Wrappers/CorDebug/ICorDebugProcess.cs | 23 +++ 4 files changed, 92 insertions(+), 75 deletions(-) create mode 100644 src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugProcess.cs diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj index a83a194643..b8e9b1c97b 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj @@ -318,6 +318,7 @@ + diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs index 5a4bf550fb..6a90a851b3 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Process-StateControl.cs @@ -177,7 +177,7 @@ namespace Debugger { AssertRunning(); - corProcess.Stop(5000); // TODO: Hardcoded value + corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway CreatePauseSession(PausedReason.ForcedBreak); CreateDebuggeeState(); @@ -216,10 +216,6 @@ namespace Debugger { AssertPaused(); - if (callbackInterface.IsInCallback) { - throw new DebuggerException("Can not continue from within callback."); - } - ExpirePauseSession(); corProcess.Continue(0); } @@ -229,14 +225,14 @@ namespace Debugger // Resume stoped tread if (this.IsPaused) { // We might get more callbacks so we should maintain consistent sate - AsyncContinue(); // TODO: Remove this... + //AsyncContinue(); // Continue the process to get remaining callbacks } // Expose race condition - drain callback queue System.Threading.Thread.Sleep(0); // Stop&terminate - both must be called - corProcess.Stop(5000); // TODO: ...and this + corProcess.Stop(uint.MaxValue); corProcess.Terminate(0); } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs index 308ef36a4f..fc2d17029c 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs @@ -24,7 +24,7 @@ namespace Debugger class ManagedCallback { Process process; - bool pauseProcessInsteadOfContinue; + bool pauseOnNextExit; bool isInCallback = false; [Debugger.Tests.Ignore] @@ -53,11 +53,12 @@ namespace Debugger // After break is pressed we may receive some messages that were already queued if (process.IsPaused && process.PauseSession.PausedReason == PausedReason.ForcedBreak) { process.TraceMessage("Processing post-break callback"); - // Continue the break, process is still breaked because of the callback - process.ExpirePauseSession(); - process.CorProcess.Continue(0); - pauseProcessInsteadOfContinue = true; + // This compensates for the break call and we are in normal callback handling mode + process.AsyncContinue_KeepDebuggeeState(); + // Start of call back - create new pause session (as usual) process.CreatePauseSession(pausedReason); + // Make sure we stay pause after the callback is handled + pauseOnNextExit = true; return; } @@ -80,28 +81,27 @@ namespace Debugger process.SelectedThread = process.GetThread(pThread); } - void ExitCallback_Continue() + void ExitCallback() { - if (pauseProcessInsteadOfContinue) { - pauseProcessInsteadOfContinue = false; - ExitCallback_Paused(); - return; + bool hasQueuedCallbacks = process.CorProcess.HasQueuedCallbacks(); + if (hasQueuedCallbacks) { + process.TraceMessage("Process has queued callbacks"); } - process.ExpirePauseSession(); - process.CorProcess.Continue(0); + // Ignore events during property evaluation + if (!pauseOnNextExit || process.Evaluating || hasQueuedCallbacks) { + process.ExpirePauseSession(); + process.CorProcess.Continue(0); + } else { + pauseOnNextExit = false; + Pause(); + } isInCallback = false; } - void ExitCallback_Paused() + void Pause() { - if (process.Evaluating) { - // Ignore events during property evaluation - ExitCallback_Continue(); - return; - } - process.SelectMostRecentStackFrameWithLoadedSymbols(); process.DisableAllSteppers(); @@ -114,8 +114,6 @@ namespace Debugger // Raise the pause event outside the callback process.Debugger.MTA2STA.AsyncCall(RaiseEvents); } - - isInCallback = false; } void RaiseEvents() @@ -149,23 +147,21 @@ namespace Debugger if (stepper.PauseWhenComplete) { if (process.SelectedThread.MostRecentStackFrame.HasSymbols) { - ExitCallback_Paused(); + pauseOnNextExit = true; } else { // This can only happen when JMC is disabled (ie NET1.1 or StepOut) if (stepper.Operation == Stepper.StepperOperation.StepOut) { // Create new stepper and keep going process.TraceMessage(" - stepping out of code without symbols at " + process.SelectedThread.MostRecentStackFrame.ToString()); new Stepper(process.SelectedThread.MostRecentStackFrame, "Stepper out of code without symbols").StepOut(); - ExitCallback_Continue(); } else { // NET1.1: There is extra step over stepper, just keep going process.TraceMessage(" - leaving code without symbols"); - ExitCallback_Continue(); } } - } else { - ExitCallback_Continue(); } + + ExitCallback(); } // Do not pass the pBreakpoint parameter as ICorDebugBreakpoint - marshaling of it fails in .NET 1.1 @@ -173,7 +169,8 @@ namespace Debugger { EnterCallback(PausedReason.Breakpoint, "Breakpoint", pThread); - ExitCallback_Paused(); + pauseOnNextExit = true; + ExitCallback(); // foreach (Breakpoint b in debugger.Breakpoints) { // if (b.Equals(pBreakpoint)) { @@ -187,21 +184,23 @@ namespace Debugger { EnterCallback(PausedReason.Other, "BreakpointSetError", pThread); - ExitCallback_Continue(); + ExitCallback(); } - public unsafe void Break(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) + public void Break(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) { EnterCallback(PausedReason.Break, "Break", pThread); - ExitCallback_Paused(); + pauseOnNextExit = true; + ExitCallback(); } public void ControlCTrap(ICorDebugProcess pProcess) { EnterCallback(PausedReason.ControlCTrap, "ControlCTrap", pProcess); - ExitCallback_Paused(); + pauseOnNextExit = true; + ExitCallback(); } public unsafe void Exception(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int unhandled) @@ -216,7 +215,7 @@ namespace Debugger // This callback should be ignored in v2 applications EnterCallback(PausedReason.Other, "Exception", pThread); - ExitCallback_Continue(); + ExitCallback(); } } @@ -228,7 +227,7 @@ namespace Debugger { EnterCallback(PausedReason.Other, "LogSwitch", pThread); - ExitCallback_Continue(); + ExitCallback(); } public void LogMessage(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, string pLogSwitchName, string pMessage) @@ -237,14 +236,14 @@ namespace Debugger process.OnLogMessage(new MessageEventArgs(process, lLevel, pMessage, pLogSwitchName)); - ExitCallback_Continue(); + ExitCallback(); } public void EditAndContinueRemap(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction, int fAccurate) { EnterCallback(PausedReason.Other, "EditAndContinueRemap", pThread); - ExitCallback_Continue(); + ExitCallback(); } public void EvalException(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) @@ -268,7 +267,8 @@ namespace Debugger eval.NotifyEvaluationComplete(!exception); process.NotifyEvaluationComplete(eval); - ExitCallback_Paused(); + pauseOnNextExit = true; + ExitCallback(); } public void DebuggerError(ICorDebugProcess pProcess, int errorHR, uint errorCode) @@ -283,14 +283,15 @@ namespace Debugger System.Windows.Forms.MessageBox.Show(errorText); - ExitCallback_Paused(); + pauseOnNextExit = true; + ExitCallback(); } public void UpdateModuleSymbols(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule, IStream pSymbolStream) { EnterCallback(PausedReason.Other, "UpdateModuleSymbols", pAppDomain); - ExitCallback_Continue(); + ExitCallback(); } #endregion @@ -303,7 +304,7 @@ namespace Debugger // Process is added in NDebugger.Start - ExitCallback_Continue(); + ExitCallback(); } public void CreateAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain) @@ -312,14 +313,14 @@ namespace Debugger pAppDomain.Attach(); - ExitCallback_Continue(); + ExitCallback(); } public void LoadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly) { EnterCallback(PausedReason.Other, "LoadAssembly", pAppDomain); - ExitCallback_Continue(); + ExitCallback(); } public unsafe void LoadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) @@ -328,7 +329,7 @@ namespace Debugger process.AddModule(pModule); - ExitCallback_Continue(); + ExitCallback(); } public void NameChange(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) @@ -337,7 +338,7 @@ namespace Debugger EnterCallback(PausedReason.Other, "NameChange: pAppDomain", pAppDomain); - ExitCallback_Continue(); + ExitCallback(); } if (pThread != null) { @@ -347,7 +348,7 @@ namespace Debugger Thread thread = process.GetThread(pThread); thread.HasBeenLoaded = true; - ExitCallback_Continue(); + ExitCallback(); } } @@ -360,14 +361,14 @@ namespace Debugger process.AddThread(pThread); - ExitCallback_Continue(); + ExitCallback(); } public void LoadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c) { EnterCallback(PausedReason.Other, "LoadClass", pAppDomain); - ExitCallback_Continue(); + ExitCallback(); } #endregion @@ -378,7 +379,7 @@ namespace Debugger { EnterCallback(PausedReason.Other, "UnloadClass", pAppDomain); - ExitCallback_Continue(); + ExitCallback(); } public void UnloadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) @@ -387,14 +388,14 @@ namespace Debugger process.RemoveModule(pModule); - ExitCallback_Continue(); + ExitCallback(); } public void UnloadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly) { EnterCallback(PausedReason.Other, "UnloadAssembly", pAppDomain); - ExitCallback_Continue(); + ExitCallback(); } public void ExitThread(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) @@ -405,7 +406,7 @@ namespace Debugger process.GetThread(pThread).NotifyNativeThreadExited(); try { - ExitCallback_Continue(); + ExitCallback(); } catch (COMException e) { // For some reason this sometimes happens in .NET 1.1 process.TraceMessage("Continue failed in ExitThread callback: " + e.Message); @@ -416,7 +417,7 @@ namespace Debugger { EnterCallback(PausedReason.Other, "ExitAppDomain", pAppDomain); - ExitCallback_Continue(); + ExitCallback(); } public void ExitProcess(ICorDebugProcess pProcess) @@ -435,21 +436,21 @@ namespace Debugger { EnterCallback(PausedReason.Other, "ChangeConnection", pProcess); - ExitCallback_Continue(); + ExitCallback(); } public void CreateConnection(ICorDebugProcess pProcess, uint dwConnectionId, IntPtr pConnName) { EnterCallback(PausedReason.Other, "CreateConnection", pProcess); - ExitCallback_Continue(); + ExitCallback(); } public void DestroyConnection(ICorDebugProcess pProcess, uint dwConnectionId) { EnterCallback(PausedReason.Other, "DestroyConnection", pProcess); - ExitCallback_Continue(); + ExitCallback(); } public void Exception2(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFrame pFrame, uint nOffset, CorDebugExceptionCallbackType exceptionType, uint dwFlags) @@ -462,15 +463,12 @@ namespace Debugger process.SelectedThread.CurrentException = new Exception(process.SelectedThread, (ExceptionType)exceptionType); - if (process.SelectedThread.CurrentException.IsUnhandled) { - ExitCallback_Paused(); - } else { - if (process.PauseOnHandledException) { - ExitCallback_Paused(); - } else { - ExitCallback_Continue(); - } + if (process.SelectedThread.CurrentException.IsUnhandled || + process.PauseOnHandledException) + { + pauseOnNextExit = true; } + ExitCallback(); } public void ExceptionUnwind(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, CorDebugExceptionUnwindCallbackType dwEventType, uint dwFlags) @@ -478,24 +476,23 @@ namespace Debugger EnterCallback(PausedReason.ExceptionIntercepted, "ExceptionUnwind", pThread); if (dwEventType == CorDebugExceptionUnwindCallbackType.DEBUG_EXCEPTION_INTERCEPTED) { - ExitCallback_Paused(); - } else { - ExitCallback_Continue(); + pauseOnNextExit = true; } + ExitCallback(); } public void FunctionRemapComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction) { EnterCallback(PausedReason.Other, "FunctionRemapComplete", pThread); - ExitCallback_Continue(); + ExitCallback(); } public void FunctionRemapOpportunity(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pOldFunction, ICorDebugFunction pNewFunction, uint oldILOffset) { EnterCallback(PausedReason.Other, "FunctionRemapOpportunity", pThread); - ExitCallback_Continue(); + ExitCallback(); } public void MDANotification(ICorDebugController c, ICorDebugThread t, ICorDebugMDA mda) @@ -508,7 +505,7 @@ namespace Debugger throw new System.Exception("Unknown callback argument"); } - ExitCallback_Continue(); + ExitCallback(); } #endregion diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugProcess.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugProcess.cs new file mode 100644 index 0000000000..f69b8b9740 --- /dev/null +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugProcess.cs @@ -0,0 +1,23 @@ +// +// +// +// +// $Revision$ +// + +#pragma warning disable 1591 + +namespace Debugger.Wrappers.CorDebug +{ + using System; + + public partial class ICorDebugProcess + { + public bool HasQueuedCallbacks() + { + int pbQueued; + this.WrappedObject.HasQueuedCallbacks(null, out pbQueued); + return pbQueued != 0; + } + } +}