I have a multi-threaded C++ application that calls some remote functions regular to tell the remote side it is still there. The remote runs a watchdog and kills the session if it does not receive a message in time.
When I debug this app in gdb
I have to set pagination
to off
and non-stop
to on
like described here.
Now I try to achieve this with the cppvsdbg
from the launch.json
in Visual Studio Code. I have installed the C++ build tools (for VS 2022) and the latest VS Code including the C/C++ development extension.
To illustrate this there is a stripped down minimal example below. The 'watchdog' sleeps for 1s. If this takes longer than 2s it exits the program otherwise it outputs a +
. The main thread outputs .
every 0.1s a hundred times. If run from console the pattern would look like +..........+..........+..........+
and so on.
When running this in a debugger and have a breakpoint inside the loop of the main method, the program will exit with code 1, if one waits for a few seconds on the breakpoint. With gdb I can set pagination=off
, non-stop=on
before I start the application. Then the watchdog thread wont be halted when the breakpoint in the loop hits. Just the pattern will look different (more +) in that case.
How to achieve this behavior with the Visual Studio debugger?
#include <iostream>
#include <chrono>
#include <thread>
#include <atomic>
using namespace std;
using namespace std::chrono_literals;
atomic_bool stop(false);
void watchdog() {
std::chrono::duration<double> max_wait(2);
while (!stop.load())
{
auto start = std::chrono::system_clock::now();
std::this_thread::sleep_for(1s);
std::chrono::duration<double> elapsed_seconds = std::chrono::system_clock::now() - start;
if (elapsed_seconds > max_wait) {
cerr << "wait took way longer than 1s" << endl;
exit(1);
} else {
cout << "+";
}
}
}
int main(int, char**){
thread wt(watchdog);
for (auto i = 0; i < 100; i++) {
std::this_thread::sleep_for(0.1s);
cout << "." << flush;
}
cout << endl;
stop = true;
wt.join();
return 0;
}
when a debugging event occurs in a windows process (exception, dll loading/unloading, thread creation/exit), the system freeze all threads in the process and sends the event to the debugger. and only after the debugger responds, thread execution thaw. that is, what you want is impossible in windows. all threads in the process will be frozen while you are under the debugger. this not depend from debugger, but windows internal design. until you under debugger, all threads in process will be not excuting
freeze/thaw have same effect as suspend/resume thread. but it use different internal counters. so thread wich freeze can not continue execution by resule (ResumeThread) and visa versa so even if try some hack - resume frozen thread - this will be not work - ResumeThread not do this and in user mode no api for thaw thread