zar
zar

Reputation: 12227

How to see real call stack in WinDbg when we break with CTRL + Break

When we have a regular breakpoint, the debugger breaks there and we see the call stack. But what if we break the execution using CTRL + Break? I would expect the currently running thread to break whererbrt it was but what I see typically is the following:

 # ChildEBP RetAddr  
00 02b7fdc4 7762f216 ntdll!DbgBreakPoint
01 02b7fdf4 76c0336a ntdll!DbgUiRemoteBreakin+0x3c
02 02b7fe00 775c9902 kernel32!BaseThreadInitThunk+0xe
03 02b7fe40 775c98d5 ntdll!__RtlUserThreadStart+0x70
04 02b7fe58 00000000 ntdll!_RtlUserThreadStart+0x1b
*** WARNING: Unable to verify checksum for ThreadDemo.exe

But how do I get to the actual code of current thread that got interrupted?

I am running a long loop as below which takes sometime and I expect it to break there.

void Bank::Deposit(void* param)
{
    Bank * bank = (Bank *)param;

    char *who = (char*) bank->bankName;

    int i;
    printf("%s: begin deposite\n", who);
    for (i = 0; i < 1000000000; i++) {
        bank->balance = bank->balance + 1;
    }
    printf("%s: done\n", who);

    return;
}

In this case when it breaks, one of the other thread does break in this function but this is a simple demo. How can I know in real windows application where did the application really stopped (and what was it doing) when I have many threads?

Upvotes: 0

Views: 2202

Answers (2)

Thomas Weller
Thomas Weller

Reputation: 59228

When you press Ctrl+C or Ctrl+Break, that keyboard event is processed by the debugger. This implies that at least one thread of the debugger is running at that time and not yours. Figuring out which thread was running before is not so easy.

The debugger will inject a new thread into your application with an int 3 instruction on the call stack. This thread is not running immediately, it first has to be scheduled by the operating system to run. This requires a context switch.

When the int 3 is reached, all threads in the process get suspended and the debugger is notified about the exception. So, between you press a key and when the threads actually stop, a time between ~15 ms and ~30 ms passes by.

However, this is nothing to worry about. Given an average human reaction time of 25 ms, millions of CPU instructions are between an observation which makes you want to stop the threads and the actual stop.

As already mentioned by Sean Cline in the comments and in the answer of Mike Vine, the other threads are stil there. You can list them with ~, show the call stacks of them using ~*k or switch to a particular thread with ~<thread>s.

Upvotes: 2

Mike Vine
Mike Vine

Reputation: 9837

There is no 'current thread that is running' when you hit ctrl-c. Zero, one or more threads may be running and so the debugger doesn't even try to work out 'which' one to break - it instead breaks in its own thread. Just because you have a single thread which is probably running at the time (but not necessarily so) doesn't change this.

But you can get what you want. When you hit ctrl-c it breaks the debugger thread and stops all other threads. You can list all threads and their callstacks by typing:

~*k

You can also switch to another thread by typing:

~Ns

where N is the ID of the thread to switch to.

Once you've set the 'current thread' to the one you want, you can type k to list its callstack and other thread specific commands.

EDIT:

see this for a decent list of windbg thread specific commands

Upvotes: 3

Related Questions