internal void OnPaused(DebuggerPausedEventArgs e) { AssertPaused(); DisableAllSteppers(); foreach (var corBreakpoint in tempBreakpoints) { corBreakpoint.Activate(0); } tempBreakpoints.Clear(); // No real purpose - just additional check if (callbackInterface.IsInCallback) { throw new DebuggerException("Can not raise event within callback."); } TraceMessage("Debugger event: OnPaused()"); if (Paused != null) { foreach (EventHandler <DebuggerPausedEventArgs> d in Paused.GetInvocationList()) { if (IsRunning) { TraceMessage("Skipping OnPaused delegate because process has resumed"); break; } if (this.TerminateCommandIssued || this.HasExited) { TraceMessage("Skipping OnPaused delegate because process has exited"); break; } d(this, e); } } }
// Calling this will prepare the paused event. // The reason for the accumulation is that several pause callbacks // can happen "at the same time" in the debugee. // The event will be raised as soon as the callback queue is drained. DebuggerPausedEventArgs RequestPause(Thread thread) { pauseOnNextExit = true; if (pausedEventArgs == null) { pausedEventArgs = new DebuggerPausedEventArgs(process); pausedEventArgs.Thread = thread; } return pausedEventArgs; }
// Calling this will prepare the paused event. // The reason for the accumulation is that several pause callbacks // can happen "at the same time" in the debugee. // The event will be raised as soon as the callback queue is drained. DebuggerPausedEventArgs RequestPause(Thread thread) { pauseOnNextExit = true; if (pausedEventArgs == null) { pausedEventArgs = new DebuggerPausedEventArgs(process); pausedEventArgs.Thread = thread; } return(pausedEventArgs); }
void ExitCallback() { bool hasQueuedCallbacks = process.CorProcess.HasQueuedCallbacks(); if (hasQueuedCallbacks) { process.TraceMessage("Process has queued callbacks"); } if (hasQueuedCallbacks) { process.AsyncContinue(DebuggeeStateAction.Keep); } else if (process.Evaluating) { // Ignore events during property evaluation pausedEventArgs = null; process.AsyncContinue(DebuggeeStateAction.Keep); } else if (pauseOnNextExit) { // process.TraceMessage("Callback exit: Paused"); process.DisableAllSteppers(); if (pausedEventArgs != null) { pausedEventArgs.Thread = threadToReport; threadToReport = null; // Raise the pause event outside the callback // Warning: Make sure that process in not resumed in the meantime DebuggerPausedEventArgs e = pausedEventArgs; // Copy for capture process.Debugger.MTA2STA.AsyncCall(delegate { process.OnPaused(e); }); } pauseOnNextExit = false; pausedEventArgs = null; } else { process.AsyncContinue(DebuggeeStateAction.Keep); } isInCallback = false; }
void ExitCallback() { bool hasQueuedCallbacks = process.CorProcess.HasQueuedCallbacks(); if (hasQueuedCallbacks) process.TraceMessage("Process has queued callbacks"); if (hasQueuedCallbacks) { process.AsyncContinue(DebuggeeStateAction.Keep); } else if (process.Evaluating) { // Ignore events during property evaluation pausedEventArgs = null; process.AsyncContinue(DebuggeeStateAction.Keep); } else if (pauseOnNextExit) { // process.TraceMessage("Callback exit: Paused"); process.DisableAllSteppers(); if (pausedEventArgs != null) { // Raise the pause event outside the callback // Warning: Make sure that process in not resumed in the meantime DebuggerPausedEventArgs e = pausedEventArgs; // Copy for capture process.Debugger.MTA2STA.AsyncCall(delegate { process.OnPaused(e); }); } pauseOnNextExit = false; pausedEventArgs = null; } else { process.AsyncContinue(DebuggeeStateAction.Keep); } isInCallback = false; }
internal void OnPaused(DebuggerPausedEventArgs e) { AssertPaused(); DisableAllSteppers(); foreach (var corBreakpoint in tempBreakpoints) { corBreakpoint.Activate(0); } tempBreakpoints.Clear(); // No real purpose - just additional check if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback."); TraceMessage ("Debugger event: OnPaused()"); if (Paused != null) { foreach(EventHandler<DebuggerPausedEventArgs> d in Paused.GetInvocationList()) { if (IsRunning) { TraceMessage ("Skipping OnPaused delegate because process has resumed"); break; } if (this.TerminateCommandIssued || this.HasExited) { TraceMessage ("Skipping OnPaused delegate because process has exited"); break; } d(this, e); } } }
void debuggedProcess_DebuggingPaused(object sender, DebuggerPausedEventArgs e) { OnIsProcessRunningChanged(EventArgs.Empty); CurrentProcess = e.Process; CurrentThread = e.Thread; CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentStackFrame : null; // We can have several events happening at the same time bool breakProcess = e.Break; // Handle thrown exceptions foreach(Thread exceptionThread in e.ExceptionsThrown) { JumpToCurrentLine(); Thread evalThread = exceptionThread; bool isUnhandled = (exceptionThread.CurrentExceptionType == ExceptionType.Unhandled); Value exception = exceptionThread.CurrentException.GetPermanentReferenceOfHeapValue(); List<Value> innerExceptions = new List<Value>(); for(Value innerException = exception; !innerException.IsNull; innerException = innerException.GetFieldValue("_innerException")) { innerExceptions.Add(innerException.GetPermanentReferenceOfHeapValue()); } // Get the exception description string stacktrace = string.Empty; for(int i = 0; i < innerExceptions.Count; i++) { if (i > 0) { stacktrace += " ---> "; } stacktrace += innerExceptions[i].Type.FullName; Value messageValue = innerExceptions[i].GetFieldValue("_message"); if (!messageValue.IsNull) { stacktrace += ": " + messageValue.AsString(); } } stacktrace += Environment.NewLine + Environment.NewLine; // Get the stacktrace string formatSymbols = StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"); string formatNoSymbols = StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}"); if (isUnhandled) { // Need to intercept now so that we can evaluate properties // Intercept may fail (eg StackOverflow) if (exceptionThread.InterceptException()) { try { // Try to evaluate the StackTrace property to get the .NET formated stacktrace for(int i = innerExceptions.Count - 1; i >= 0; i--) { Value stackTraceValue = innerExceptions[i].GetPropertyValue(evalThread, "StackTrace"); if (!stackTraceValue.IsNull) { stacktrace += stackTraceValue.AsString() + Environment.NewLine; } if (i > 0) { stacktrace += " " + StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}") + Environment.NewLine; } } } catch (GetValueException) { stacktrace += exceptionThread.GetStackTrace(formatSymbols, formatNoSymbols); } } else { stacktrace += StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptException}") + Environment.NewLine + Environment.NewLine; stacktrace += exceptionThread.GetStackTrace(formatSymbols, formatNoSymbols); } } else { // Do not intercept handled expetions stacktrace += exceptionThread.GetStackTrace(formatSymbols, formatNoSymbols); } string title = isUnhandled ? StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Unhandled}") : StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Handled}"); string type = string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Message}"), exception.Type); Bitmap icon = WinFormsResourceService.GetBitmap(isUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning"); if (DebuggeeExceptionForm.Show(e.Process, title, type, stacktrace, icon, isUnhandled)) { breakProcess = true; // The dialog box is allowed to kill the process if (e.Process.HasExited) { return; } // Intercept handled exception *after* the user decided to break if (!isUnhandled) { if (!exceptionThread.InterceptException()) { MessageService.ShowError("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptHandledException}"); } } } } // Handle breakpoints foreach (Breakpoint breakpoint in e.BreakpointsHit) { var bookmark = SD.BookmarkManager.Bookmarks.OfType<BreakpointBookmark>().First(bm => bm.InternalBreakpointObject == breakpoint); if (string.IsNullOrEmpty(bookmark.Condition)) { breakProcess = true; } else { if (EvaluateCondition(bookmark.Condition)) { breakProcess = true; DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAtBecause}") + "\n", bookmark.LineNumber, bookmark.FileName, bookmark.Condition)); } } } if (breakProcess) { JumpToCurrentLine(); RefreshPads(); } else { e.Process.AsyncContinue(); } }
// Calling this will prepare the paused event. // The reason for the accumulation is that several pause callbacks // can happen "at the same time" in the debugee. // The event will be raised as soon as the callback queue is drained. DebuggerPausedEventArgs GetPausedEventArgs() { return(pausedEventArgs ?? (pausedEventArgs = new DebuggerPausedEventArgs(process))); }
// Calling this will prepare the paused event. // The reason for the accumulation is that several pause callbacks // can happen "at the same time" in the debugee. // The event will be raised as soon as the callback queue is drained. DebuggerPausedEventArgs GetPausedEventArgs() { return pausedEventArgs ?? (pausedEventArgs = new DebuggerPausedEventArgs(process)); }