'problem internal to GDB has been detected and debugging session dies in multi-thread environment

My test code is like this:

#include <iostream>
#include <string>
#include <thread>
#include <unistd.h>

using namespace std;

class ns_string {
public:
    ns_string(string s) : _s(s) {}
    static ns_string make_ns_string(const string &s) {
        return ns_string(s);
    }
    string ns() const { return _s; }
private:
    string _s;
};


void f2(string s) {
    cout << "f2:" << s << endl;
}
void thread_func() {
    while (1) {
        cout << "------------------ another thread -> ";
        f2("thread_func");
        sleep(5);
    }
}

void f(int i, const ns_string& name) {
    cout << i << ", " << name.ns() << endl;
    f2(name.ns());
}

int main(int argc,char* argv[]) {
    thread t(thread_func);

    for (int i=0; i<10; i++) {
        f(i, ns_string::make_ns_string(std::to_string(i)));
    }

    t.join();
    return 0;
}

I want to set a breakpoint when f2 parameter s == "4".
I do that via b f2 if strcmp(s.c_str(), "4") == 0.

Here're three cases that I experiment.

GDB version is 11.1

case 1

DONOT start thread_func. Everything is ok. The program stops when s=="4"

(gdb) r
0, 0
f2:0
1, 1
f2:1
2, 2
f2:2
3, 3
f2:3
4, 4

Breakpoint 1, f2 (s="4") at gdb-crash.cc:21
21      cout << "f2:" << s << endl;

case 2

Start thread_func, but DONOT call f2. gdb outputs:

(gdb) r
[New Thread 0xffffbf17c1c0 (LWP 20299)]
------------------ another thread -> 0, 0
Error in testing breakpoint condition:
Unable to fetch general registers.: No such process.
An error occurred while in a function called from GDB.
Evaluation of the expression containing the function
(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str() const) will be abandoned.
When the function is done executing, GDB will silently stop.
Selected thread is running.
(gdb) c
Continuing.
f2:0
1, 1
f2:1
2, 2
f2:2
3, 3
f2:3
4, 4

Thread 1 "a.out" hit Breakpoint 1, f2 (s="4") at gdb-crash.cc:21
21      cout << "f2:" << s << endl;

However I try to continue, it still can stop at s=="4.

case 3

Start the thread_func, and call f2

Program die. gdb outputs:

Error in testing breakpoint condition:
The program stopped in another thread while making a function call from GDB.
Evaluation of the expression containing the function
(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::c_str() const) will be abandoned.
When the function is done executing, GDB will silently stop.
[Switching to Thread 0x7ffff7a47740 (LWP 1832)]

Thread 1 "a.out" hit Breakpoint 1, f2 (s="0") at a.cc:30
30          cout << "f2:" << s << endl;
Missing separate debuginfos, use: dnf debuginfo-install libgcc-11.2.1-9.fc34.x86_64 libstdc++-11.2.1-9.fc34.x86_64
../../gdb/infcall.c:1284: internal-error: value* call_function_by_hand_dummy(value*, type*, gdb::array_view<value*>, void (*)(void*, int), void*): Assertion `call_thread->thread_fsm == sm' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.

Obviously different threads access f2, which confuses gdb for some reason.

As a debugger, I don't care about which thread stops at that breakpoint. I only care about gdb makes it stop when my condition is met. How should I acheive that in multi-thread situation ?



Solution 1:[1]

This is a bug in GDB. Reproduced using current GDB trunk and GDB-10.0.

Assuming you are using g++ to build the code, here is a workaround:

(gdb) b f2 if s._M_dataplus._M_p[0] == '4' && s._M_dataplus._M_p[1] == '\0'

The most likely reason for the bug is that calling s.c_str() requires that the inferior (being debugged) program be resumed, and while it's running to evaluate s.c_str() another thread hits the breakpoint, causing GDB to become confused.

Similar (but not identical) bug.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1