// Invoked when ContextMenu item is selected to toggle Frozen/Thawed status. // This is invoked on the currently selected thread, and that can't change while the ContextMenu is up. // Called on UI thread. void OnThreadFrozenToggled(Object sender, EventArgs args) { MDbgThread t = this.SelectedItem; MainForm.ExecuteOnWorkerThreadIfStoppedAndBlock(delegate(MDbgProcess proc) { Debug.Assert(proc != null); Debug.Assert(!proc.IsRunning); CorDebugThreadState state = t.CorThread.DebugState; bool fFrozen = (state & CorDebugThreadState.THREAD_SUSPEND) == CorDebugThreadState.THREAD_SUSPEND; if (fFrozen) { // Thaw the thread state &= ~CorDebugThreadState.THREAD_SUSPEND; } else { // Freeze the thread state |= CorDebugThreadState.THREAD_SUSPEND; } t.CorThread.DebugState = state; }); // Need to redraw the window. this.RefreshToolWindow(); }
// Is the MDbgThread frozen? // Must be called on worker thread. private static bool IsFrozen(MDbgThread t) { CorDebugThreadState state = t.CorThread.DebugState; bool fFrozen = (state & CorDebugThreadState.THREAD_SUSPEND) == CorDebugThreadState.THREAD_SUSPEND; return(fFrozen); }
// Set the current debug state of each thread. public void SetAllThreadsDebugState( CorDebugThreadState state, DebuggedThread exceptThis) { m_controller.SetAllThreadsDebugState(state, exceptThis != null ? exceptThis.GetInterface() : null); }
/// <summary> /// Gets the current debug state of this thread. /// </summary> /// <remarks> /// If the process is currently stopped, <see paramref="state" /> /// represents the debug state that would exist for this thread /// if the process were to be continued, not the actual current /// state of this thread. /// </remarks> public int GetDebugState(out CorDebugThreadState state) { int pState = default; int result = Calli(_this, This[0]->GetDebugState, &pState); state = (CorDebugThreadState)pState; return(result); }
int ICorDebugThread.GetDebugState(out CorDebugThreadState pState) { Debug.Assert(!IsVirtualThread); pState = IsLogicalThreadSuspended ? CorDebugThreadState.THREAD_SUSPEND : CorDebugThreadState.THREAD_RUN; return(Utility.COM_HResults.S_OK); }
int ICorDebugThread.SetDebugState(CorDebugThreadState state) { Debug.Assert(!IsVirtualThread); //This isnt' quite right, there is a discrepancy between CorDebugThreadState and CorDebugUserState //where the TinyCLR only has one thread state to differentiate between running, waiting, and stopped this.IsSuspended = (state != CorDebugThreadState.THREAD_RUN); return(Utility.COM_HResults.S_OK); }
/// <param name="threadsToRun"> Null to keep current setting </param> /// <param name="newThreadState"> What happens to created threads. Null to keep current setting </param> internal void AsyncContinue(DebuggeeStateAction action, Thread[] threadsToRun, CorDebugThreadState?newThreadState) { AssertPaused(); if (threadsToRun != null) { // corProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND, null); // Note: There is unreported thread, stopping it prevents the debugee from exiting // It is not corProcess.GetHelperThreadID // ICorDebugThread[] ts = new ICorDebugThread[corProcess.EnumerateThreads().GetCount()]; // corProcess.EnumerateThreads().Next((uint)ts.Length, ts); foreach (Thread t in this.Threads) { CorDebugThreadState state = Array.IndexOf(threadsToRun, t) == -1 ? CorDebugThreadState.THREAD_SUSPEND : CorDebugThreadState.THREAD_RUN; try { t.CorThread.SetDebugState(state); } catch (COMException e) { // The state of the thread is invalid. (Exception from HRESULT: 0x8013132D) // It can happen for example when thread has not started yet if ((uint)e.ErrorCode == 0x8013132D) { // TraceMessage("Can not suspend thread - The state of the thread is invalid. Thread ID = " + t.CorThread.GetID()); } else { throw; } } } } if (newThreadState != null) { this.NewThreadState = newThreadState.Value; } NotifyResumed(action); corProcess.Continue(0); if (this.Options.Verbose) { this.TraceMessage("Continue"); } if (action == DebuggeeStateAction.Clear) { OnResumed(); } }
int ICorDebugThread.SetDebugState(CorDebugThreadState state) { Debug.Assert(!IsVirtualThread); //This isnt' quite right, there is a discrepancy between CorDebugThreadState and CorDebugUserState //where the nanoCLR only has one thread state to differentiate between running, waiting, and stopped if (state != CorDebugThreadState.THREAD_RUN) { Suspend().Wait(); } else { Resume().Wait(); } return(COM_HResults.S_OK); }
/// <summary> /// Sets the debug state of all managed threads in the process. /// </summary> /// <param name="state"> /// A value of the that specifies the target state of the thread for debugging. /// </param> /// <param name="exceptThisThread"> /// The thread that should be exempted from the debug state setting. If this value /// is <see langword="null" />, no thread is exempted. /// </param> /// <remarks> /// This method may affect threads that are not visible via <see cref="EnumerateThreads(out CorDebugEnum{CorDebugThread})" />, /// so threads that were suspended with this method will need to be resumed. /// </remarks> public int SetAllThreadsDebugState(CorDebugThreadState state, CorDebugThread exceptThisThread) { using var pExceptThisThread = exceptThisThread?.AcquirePointer(); return(Calli(_this, This[0]->SetAllThreadsDebugState, (int)state, pExceptThisThread)); }
public ThreadInfo(CorThread thread) { Thread = thread; State = thread.State; }
/// <summary> /// Sets flags that describe the debugging state of this thread. /// </summary> /// <param name="state"> /// The new debugging state for this thread. /// </param> /// <remarks> /// This method sets the current debug state of the thread. (The /// "current debug state" represents the debug state if the process /// were to be continued, not the actual current state.) The normal /// value for this is <see cref="CorDebugThreadState.THREAD_RUN" />. /// Only the debugger can affect the debug state of a thread. Debug /// states do last across continues, so if you want to keep a thread /// in <see cref="CorDebugThreadState.THREAD_SUSPEND" /> over multiple /// continues, you can set it once and thereafter not have to worry /// about it. Suspending threads and resuming the process can cause /// deadlocks, though it's usually unlikely. This is an intrinsic /// quality of threads and processes and is by-design. A debugger can /// asynchronously break and resume the threads to break the deadlock. /// If the thread's user state includes <see cref="CorDebugUserState.USER_UNSAFE_POINT" />, /// then the thread may block a garbage collection (GC). This means /// the suspended thread has a much higher chance of causing a /// deadlock. This may not affect debug events already queued. /// Thus a debugger should drain the entire event queue (by calling /// <see cref="CorDebugController.HasQueuedCallbacks(CorDebugThread, out bool)" /> before /// suspending or resuming threads. Else it may get events on a /// thread that it believes it has already suspended. /// </remarks> public int SetDebugState(CorDebugThreadState state) => Calli(_this, This[0]->SetDebugState, (int)state);
int ICorDebugAppDomain.SetAllThreadsDebugState(CorDebugThreadState state, ICorDebugThread pExceptThisThread) { return(this.ICorDebugController.SetAllThreadsDebugState(state, pExceptThisThread)); }
public ThreadInfo(CorThread thread) { this.Thread = thread; this.State = thread.State; }
int ICorDebugThread.SetDebugState(CorDebugThreadState state) { Debug.Assert(!IsVirtualThread); //This isnt' quite right, there is a discrepancy between CorDebugThreadState and CorDebugUserState //where the TinyCLR only has one thread state to differentiate between running, waiting, and stopped this.IsSuspended = (state != CorDebugThreadState.THREAD_RUN); return Utility.COM_HResults.S_OK; }
int ICorDebugController.SetAllThreadsDebugState( CorDebugThreadState state, ICorDebugThread pExceptThisThread ) { return ((ICorDebugController)m_process).SetAllThreadsDebugState(state, pExceptThisThread); }
public void SetAllThreadsDebugState(CorDebugThreadState state, CorThread exceptThis) { m_controller.SetAllThreadsDebugState(state, exceptThis != null ? exceptThis.GetInterface() : null); }
private static void ThreadResumeSuspendHelper(ArgParser ap, CorDebugThreadState newState, bool showWarnings) { int threadNumber; if (ap == null) { throw new ArgumentException(); } if (ap.Exists(0)) { if (ap.AsString(0) == "*") { // do an action on all threads foreach (MDbgThread t in Debugger.Processes.Active.Threads) { SetDebugStateWrapper(t, newState, showWarnings); } } else if (ap.AsString(0).StartsWith("~")) { threadNumber = Int32.Parse(ap.AsString(0).Substring(1), CultureInfo.CurrentUICulture); // it's ~number syntax -- do on all threads except this one. foreach (MDbgThread t in Debugger.Processes.Active.Threads) { if (t.Number != threadNumber) { SetDebugStateWrapper(t, newState, showWarnings); } } } else { MDbgThread t = g_threadNickNames.GetThreadByNickName(ap.AsString(0)); if (t == null) { throw new ArgumentException(); } SetDebugStateWrapper(t, newState, showWarnings); } } else { SetDebugStateWrapper(Debugger.Processes.Active.Threads.Active, newState, showWarnings); } }
// Helper to set the debug state and ignore certain errors. // Throws on error. static void SetDebugStateWrapper(MDbgThread t, CorDebugThreadState newState, bool showWarnings) { if ((newState == CorDebugThreadState.THREAD_SUSPEND) && ((t.CorThread.UserState & CorDebugUserState.USER_UNSAFE_POINT) != 0)) { // Hard-suspending a thread while the thread is not at GC-safe point is bad. // If the users resumes a process and the GC triggers, the GC suspension logic // will not be able to suspend because it will wait forever on the thread that // is not at the GC safe point. However, in this scenario, a debugger can always // async-break and resume the suspended thread to avoid a live lock. So we just // issue a warning here. if (showWarnings) { WriteOutput("Warning: You are suspending Thread " + t.Number + " at an unsafe spot."); WriteOutput("Until you resume this thread, the process may block if a garbage collection occurs."); WriteOutput("To unblock the process, you need to asynchronously break the process (e.g. Ctrl-C) and resume the thread."); } } try { t.CorThread.DebugState = newState; } catch (System.Runtime.InteropServices.COMException e) { if (e.ErrorCode == (int)HResult.CORDBG_E_BAD_THREAD_STATE) // CORDBG_E_BAD_THREAD_STATE { if (showWarnings) { WriteOutput(MDbgOutputConstants.Ignore, "Warning: Thread " + t.Number + " can't be set to " + newState); } return; // thread is unavailable, ignore it } throw; // let error propogate up. } }
public void SetDebugState(CorDebugThreadState state) { this.WrappedObject.SetDebugState(((Interop.CorDebug.CorDebugThreadState)(state))); }
int ICorDebugController.SetAllThreadsDebugState(CorDebugThreadState state, ICorDebugThread pExceptThisThread) { // could/should really make this one call to engine...or else send them all at once.. CorDebugThread threadExcept = (CorDebugThread)pExceptThisThread; foreach (CorDebugThread thread in GetAllNonVirtualThreads()) { if (thread != threadExcept) { DebugAssert(!thread.GetLastCorDebugThread().IsVirtualThread); ((ICorDebugThread)thread).SetDebugState(state); } } return Utility.COM_HResults.S_OK; }
public static void SetAllThreadsDebugState(this ICorDebugProcess instance, CorDebugThreadState state, ICorDebugThread pExceptThisThread) { instance.__SetAllThreadsDebugState(state, pExceptThisThread); }
public static void SetDebugState(this ICorDebugThread instance, CorDebugThreadState state) { instance.__SetDebugState(state); }
/// <summary> /// Sets the debug state of all managed threads /// </summary> /// <param name="state">New state</param> /// <param name="thread">Thread to exempt from the new state or null</param> public void SetAllThreadsDebugState(CorDebugThreadState state, CorThread thread = null) => obj.SetAllThreadsDebugState(state, thread?.RawObject);
int ICorDebugAppDomain.SetAllThreadsDebugState( CorDebugThreadState state, ICorDebugThread pExceptThisThread ) { return this.ICorDebugController.SetAllThreadsDebugState(state, pExceptThisThread); }
/// <param name="threadsToRun"> Null to keep current setting </param> /// <param name="newThreadState"> What happens to created threads. Null to keep current setting </param> internal void AsyncContinue(DebuggeeStateAction action, Thread[] threadsToRun, CorDebugThreadState? newThreadState) { AssertPaused(); if (threadsToRun != null) { // corProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND, null); // Note: There is unreported thread, stopping it prevents the debugee from exiting // It is not corProcess.GetHelperThreadID // ICorDebugThread[] ts = new ICorDebugThread[corProcess.EnumerateThreads().GetCount()]; // corProcess.EnumerateThreads().Next((uint)ts.Length, ts); foreach(Thread t in this.Threads) { CorDebugThreadState state = Array.IndexOf(threadsToRun, t) == -1 ? CorDebugThreadState.THREAD_SUSPEND : CorDebugThreadState.THREAD_RUN; try { t.CorThread.SetDebugState(state); } catch (COMException e) { // The state of the thread is invalid. (Exception from HRESULT: 0x8013132D) // It can happen for example when thread has not started yet if ((uint)e.ErrorCode == 0x8013132D) { // TraceMessage("Can not suspend thread - The state of the thread is invalid. Thread ID = " + t.CorThread.GetID()); } else { throw; } } } } if (newThreadState != null) { this.NewThreadState = newThreadState.Value; } NotifyResumed(action); corProcess.Continue(0); if (this.Options.Verbose) { this.TraceMessage("Continue"); } if (action == DebuggeeStateAction.Clear) { OnResumed(); } }
public ThreadInfo(CorThread thread) { this.Thread = thread; this.State = thread.State; }
int ICorDebugThread.GetDebugState(out CorDebugThreadState pState) { Debug.Assert(!IsVirtualThread); pState = IsLogicalThreadSuspended ? CorDebugThreadState.THREAD_SUSPEND : CorDebugThreadState.THREAD_RUN; return Utility.COM_HResults.S_OK; }
internal THREADSTATE ConvertState(CorDebugThreadState internalState) { THREADSTATE state = THREADSTATE.INVALID; switch (internalState) { case CorDebugThreadState.THREAD_RUN: state = THREADSTATE.RUNNING; break; case CorDebugThreadState.THREAD_SUSPEND: state = THREADSTATE.SUSPENDED; break; default: state = THREADSTATE.INVALID; break; } return state; }
int ICorDebugController.SetAllThreadsDebugState(CorDebugThreadState state, ICorDebugThread pExceptThisThread) { return(((ICorDebugController)m_process).SetAllThreadsDebugState(state, pExceptThisThread)); }
public void SetAllThreadsDebugState(CorDebugThreadState state, ICorDebugThread pExceptThisThread) { this.WrappedObject.SetAllThreadsDebugState(((Debugger.Interop.CorDebug.CorDebugThreadState)(state)), pExceptThisThread.WrappedObject); }
public ThreadInfo(CorThread thread) { Thread = thread; State = thread.State; }
/// <summary> /// Sets the debug state of all managed threads /// </summary> /// <param name="state">New state</param> /// <param name="thread">Thread to exempt from the new state or null</param> public void SetAllThreadsDebugState(CorDebugThreadState state, CorThread thread = null) { int hr = obj.SetAllThreadsDebugState(state, thread == null ? null : thread.RawObject); }
// Helper to set the debug state and ignore certain errors. // Throws on error. private static void SetDebugStateWrapper(MDbgThread t, CorDebugThreadState newState) { try { t.CorThread.DebugState = newState; } catch (COMException e) { if (e.ErrorCode == (int) HResult.CORDBG_E_BAD_THREAD_STATE) // CORDBG_E_BAD_THREAD_STATE { WriteOutput(MDbgOutputConstants.Ignore, "Warning: Thread " + t.Id + " can't be set to " + newState); return; // thread is unavailable, ignore it } throw; // let error propogate up. } }