I have an abstract base class that has the logic that handles the lifecycle of a thread (start, stop, join). The work executed in the thread depends on the derived class that is instantiated, and there are several derived classes.
The base class looks like this:
class Base {
public:
Base(int i, bool b) : i{i}, b{b}
{
start();
}
virtual bool getB() { return b; };
void stop() { stopWorking = true; workerTh.join(); };
protected:
virtual void start()
{
std::cout << "Base start method" << std::endl;
workerTh = std::thread{ std::bind(&Derived::work, this) };
};
virtual void work() = 0;
std::thread workerTh;
int i;
bool b;
bool stopWorking = false;
};
A derived class looks like this:
class Derived : public Base {
public:
Derived(int i, bool b) : Base(i,b) {};
protected:
void work()
{
std::cout << "Derived Work started!" << std::endl;
while (not stopWorking)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
std::cout << "Derived Work ended!" << std::endl;
}
};
It runs as expected in a regular program like:
int main()
{
std::cout << "Starting" << std::endl;
Derived d { 10, false};
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::cout << "Finishing" << std::endl;
d.stop();
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
But if I execute it in a google test then I get a coredump and the cause is that I'm invoking a pure virtual method in this line:
workerTh = std::thread{ std::bind(&Base::work, this) };
So, why does that line work as expected in a normal program, but crashes in a google test? Am I missing something when launching GTest?
This is the test:
#include "BaseDerived.cc"
#include "gtest/gtest.h"
TEST(BaseDerivedWithThreadTest, FailsCoredumpCallingPureVirtual) {
Derived d { 10, false };
ASSERT_FALSE (d.getB());
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from BaseDerivedWithThreadTest
[ RUN ] BaseDerivedWithThreadTest.FailsCoredumpCallingPureVirtual
Base start method
terminate called without an active exception
pure virtual method called
terminate called recursively
Aborted (core dumped)
I can overcome this issue by putting the thread lifecycle code down to the derived classes, but I find it very ugly just to make googletest happy.
Any ideas?
Thanks!