0

I am trying to display the stack traces of RTOS fibers running in a C++ solution in VS2022. Since upgrading to Windows 11 there seems to be a problem in the implementation. The existing approach, which has worked with VS2013 and VS2019 uses context switching to switch the context of the fiber with a dummy thread (that is always suspended)

I have written a VSPackage that uses debugger events to handle the context switching and react to events. When the debugger stops I switch the contexts and then when execution starts I restore the original thread context. If the debugger stops at a breakpoint everything is fine and the dummy threads stacks are correct. If I step in/out/over or hit the pause execution even though the context have been switched it displays incorrectly.

One method I have tried is to use a worker thread within my VSPackage is to freeze/suspend all but one thread, try and step the code for that thread, and then thaw/resume the other threads. However, I have found this method to be unreliable. What I want to do is force the VS2022 threads window to update but AI suggests it cannot be done.

My question is: has anyone else tried something similar and have they had any success?

Providing code would be far to complex but the basic pseudo code is given below. It is written in C#

//Contains fiber information plus the dummy thread ID
// for each fiber and fiber and thread contexts
FiberArray[];

//Debugger event
public int OnModeChange(DBGMODE mode)
{
    if (DBGMODE.DBGMODE_Break == mode)
    {
       SwitchFiberContexts();
    }
    else if (DBGMODE.DBGMODE_Run == mode)
    {
        for (int f = 0; f < FiberArray.Count, ++f)
        {
           RestoreWindowsThreadContext(FiberArray[f]);
        }
    }
}
      
private void SwitchFiberContexts()
{
    //Read register contexts for fibers from process being debugged
    //...
    //...


    for (int f = 0; f < FiberArray.Count, ++f)
    {
        StoreWindowsThreadContext(FiberArray[f]);

        //Replace dummy thread context with fiber context
        ReplaceWindowsThreadContext(FiberArray[f]);
    }
}
New contributor
Sparky_335 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
2
  • 1
    Is it C# or C++? You might have to edit the tags. Commented Nov 18 at 12:39
  • The extension is written in C#, but there is also a C++ DLL in the solution that provided the interface to the code being debugged. The target solution is C++ (32 bit). Basically what happens is when the target solution hits a breakpoint, step event etc. I read the fiber contexts. I then overwrite the dummy window threads with these contexts to provide the user with the current state of the target solution. This method has worked well for VS2013 through to VS2019 but since VS2022 became the preferred development system it no longer works. Commented Nov 19 at 7:42

1 Answer 1

3

The reason your approach is acting weird in VS2022 is probs because of how the debugger caches stack frames compared to older 32-bit versions. It doesn’t let you make arbitrary changes to the register context in a way that sticks while stepping or running live. when you load a saved context into a dummy thread, VS basically still treats the thread as the active context and resets registers whenever you step, so your SwitchFiberContexts method ends up fighting the internal state. If you check the Debugger Contexts docs and Expression Evaluation Context, it shows that the debugger relies on the current register context to evaluate stacks and locals. The Changing Contexts doc even says that whenever execution, stepping, or tracing happens, the register context gets immediately reset to match the program counter. That’s why your manual SwitchFiberContexts doesn’t stick haha. WinDbg handles this differently like you can see in the .thread Set Register Context reference that it explicitly allows overriding register context for stack ops. VS2022’s debugger doesn’t have a supported way to maintain that override while stepping.

From my experience, the only way to get this reliably working in VS2022 is to stop doing register swapping in a VSPackage and either:

  • Use the Concord API (specifically DkmCallStackFilter) to virtualize frames, orr

  • Skip the native Threads window and render the fiber stacks in a custom tool window where the debugger won’t overwrite the data every step since that was the problem

Both work, the first is more “official” but tricky, the second is simpler if you just wanna see the stacks without VS throwing a tantrum every step lmao

New contributor
Mykal Steele is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, that's a help. I have already tried to implement the second option you suggested. This works fine and I have a custom window that can display the fiber stacks in a similar method to the native Threads window. The problem is that because the information is not decoded in the native window I don't have access to variables within each stack frame. This is important for the users of the system when they are debugging. Trying to provide a custom solution that can also decode complex local variables is way beyond what I can offer. Switching the context has worked well prior to VS2022.
That’s actually the main reason I suggested the Concord API (Dkm callstack filter thing). Have you tried it? It will inject your fiber frames directly into the native Call Stack window, and they live there so VS can just apply its own built-in Expression Evaluator to them automatically. This will give you full access to local variables and you won't need to decode anything.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.