C++11 std::thread and virtual function binding - c++

I ran into a weird C++ code behaviour, not sure whether it's a compiler bug or simply undefined/unspecified behaviour of my code. Here is the code:
#include <unistd.h>
#include <iostream>
#include <thread>
struct Parent {
std::thread t;
static void entry(Parent* p) {
p->init();
p->fini();
}
virtual ~Parent() { t.join(); }
void start() { t = std::thread{entry, this}; }
virtual void init() { std::cout << "Parent::init()" << std::endl; }
virtual void fini() { std::cout << "Parent::fini()" << std::endl; }
};
struct Child : public Parent {
virtual void init() override { std::cout << "Child::init()" << std::endl; }
virtual void fini() override { std::cout << "Child::fini()" << std::endl; }
};
int main() {
Child c;
c.start();
sleep(1); // <========== here is it
return 0;
}
The output of the code would be the following, which isn't surprising:
Child::init()
Child::fini()
However, if the function call "sleep(1)" is commented out, the output would be:
Parent::init()
Parent::~fini()
Tested on Ubuntu 15.04, both gcc-4.9.2 and clang-3.6.0 show the same behaviour. Compiler options:
g++/clang++ test.cpp -std=c++11 -pthread
It looks like a race condition (the vtable not fully constructed before the thread starts). Is this code ill-formed ? a compiler bug ? or it's supposed to be like this ?

#KerrekSB commented:
” The thread uses the child object, but the child object is destroyed before the thread is joined (because the joining only happens after the destruction of the child has begun).
The Child object is destroyed at the end of main. The Child destructor is executed, and effectively calls the Parent destructor, where Parent bases (no such) and data members (the thread object) are destroyed. As destructors are invoked up the chain of base classes the dynamic type of the object changes, in reverse order of how it changes during construction, so at this point the type of the object is Parent.
The virtual calls in the thread function can happen before, overlapping with or after the call of the Child destructor, and in the case of overlapping there's one thread accessing storage (in practice, the vtable pointer) that is being changed by another thread. So this is Undefined Behavior.

This is common design issue; what you tried to do is a classical anti-pattern.
Parent cannot be at the same time a thread manager, starting a thread and waiting for thread termination:
virtual ~Parent() { t.join(); }
void start() { t = std::thread{entry, this}; }
and also a thread object:
virtual void init() { std::cout << "Parent::init()" << std::endl; }
virtual void fini() { std::cout << "Parent::fini()" << std::endl; }
These are two distinct concepts, with strictly incompatible specifications.
(And thread objects are not useful in general.)

Related

Synchronization in destructor: Why not? How?

Or... how to properly combine Concurrency, RAII and Polymorphism?
This is a very practical issue. We were bitten by this combination, summarized as Chandler Carruth's terrifying bug (at 1:18:45 mark)!
If you like bugs, try to catch the puzzle here (adapted from Chandler's talk):
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
class A {
public:
virtual void F() = 0;
void Done() {
std::lock_guard<std::mutex> l{m};
is_done = true;
cv.notify_one();
std::cout << "Called Done..." << std::endl;
}
virtual ~A() {
std::unique_lock<std::mutex> l{m};
std::cout << "Waiting for Done..." << std::endl;
cv.wait(l, [&] {return is_done;});
std::cout << "Destroying object..." << std::endl;
}
private:
std::mutex m;
std::condition_variable cv;
bool is_done{false};
};
class B: public A {
public:
virtual void F() {}
~B() {}
};
int main() {
A *obj{new B{}};
std::thread t1{[=] {
obj->F();
obj->Done();
}};
delete obj;
t1.join();
return 0;
}
The issue (spotted when compiled via clang++ -fsanatize=thread) boils down to a race between a read of the virtual table (polymorphism) and a write on it (before entering ~A). The write being done as part of the destruction chain (so no method from B is called in A's destructor).
The recommended workaround is to move the synchronization outside the destructor, forcing each client of the class to call a WaitUntilDone/Join method. This is easy to forget and that's exactly why we wanted to use the RAII idiom in the first place.
Thus, my questions are:
Is there a nice way to enforce synchronization in base destructor?
Out of curiosity, why on earth the virtual table is even used from the destructor? I would have expected static binding here.
You can use an RAII wrapper for objects that can't support RAII semantics directly. The wrapper object's constructor can construct the inner object and then do anything that's logically part of construction but can only be done after the inner object's constructor returns. Similarly, the wrapper object's destructor can do anything that has to be done before the inner object's destructor can safely be invoked and then it can destroy the inner object.

Guarding against vtable data race in derived destructor

Suppose I have the following code
#include <thread>
#include <iostream>
#include <atomic>
struct FooBase {
void start(){
run_condition_ = true;
t_ = std::thread([this](){
thread_handler();
});
}
virtual ~FooBase(){
run_condition_ = false;
if(t_.joinable())
t_.join();
}
protected:
virtual void thread_handler() = 0;
std::atomic_bool run_condition_{false};
private:
std::thread t_;
};
struct Foo : FooBase {
void thread_handler() override {
while(run_condition_){
std::cout << "Foo derived thread.." << std::endl;
}
}
};
int main(){
Foo f;
f.start();
getchar();
return 0;
}
Here I think because the destructor of the derived class Foo is called before FooBase the thread_handler vtable lookup happens in the base class IF the thread has not yet joined (still running) when the destructor of Foo is done. Since FooBase::thread_handler is pure virtual I am essentially guranteed a sigabort.
How do I guard against this? I hack my way through by not having thread_handler as pure virtual
virtual void thread_handler(){}
But I am lost as to how I can guard against this in the baseclass itself, I can implement a join_thread interface in the base class and call this from every derived class, but this seems cumbersome.
There's two issues here, neither of which match precisely what you described.
Your thread only gets stopped in ~FooBase(). This means that if Foo::thread_handler ever reads or writes to any of its members, they will get destroyed out from under it before the thread is stopped.
It you get to the destructor fast enough, it's possible that start() won't have actually invoked thread_handler() on the new thread by the time Foo gets destroyed - which will lead to the pure virtual call.
Either way, you need to ensure that by the time Foo is destroyed, anything related to thread_handler is done. This implies that every derived class from FooBase has to have, in its destructor:
run_condition_ = false;
if (t_.joinable()) {
t_join();
}
Setting aside that this directly doesn't work because t_ is private (you could wrap that into a protected stop()), it's an awkward design if all of your derived classes need to do something special just to work. You could instead put FooBase into its own class that just takes an arbitrary callable as an argument:
class joining_thread {
public:
joining_thread() = default;
~joining_thread() { stop(); }
bool running() const { return run_condition_.load(); }
template <typename... Args>
void start(Args&&... args) {
run_condition_ = true;
t_ = std::thread(std::forward<Args>(args)...);
}
void stop() {
run_condition_ = false;
if (t_.joinable()) t_.join();
}
private:
std::thread t_;
std::atomic_bool run_condition_{false};
};
And then your Foo can just have that as a member:
class Foo {
public:
void start() {
t_.start([this]{
while (t_.running()) { ... }
});
}
private:
// just make me the last member, so it's destroyed first
joining_thread t_;
};
That's still a little awkward with the whole running() thing, but hopefully the idea makes sense.
What you describe is not possible. You call "start" after you have constructed the object. The object is at that stage valid. You have avoided the common problem of calling a virtual function in the constructor, which would have caused issues. There is something called a memory barrier that is implied by any thread calls, so you can count on the fact the new thread will start with a view of memory that existed at the point it was created. Any thing that existed AND was not changed, is fine.
Your problem (as described in another answer) is that you can exit and destroy the object (and it's vtable), before the thread is complete.
The simplest fix for this is use a packaged task. Calling "get" on the future ensures the task is finished before you continue. Consider the code below
#include "stdafx.h"
#include <thread>
#include <iostream>
#include <atomic>
#include <future>
int main()
{
std::atomic<bool> stop{ false };
std::future<void> sync;
std::packaged_task<void()> task([&stop]()
{
while (!stop)
{
std::cout << "Running\n";
}
});
std::thread thread([&task]() {task();});
getchar();
stop = true;
task.get_future().get();
thread.join();
return 0;
}

Inheritance, background thread and RAII

I have a base class that can start background thread, and stop it when needed. That thread calls two virtual methods Open() and Close(). So all inherited classes can re-implement this methods, but not starting/stoping thread routine (it more difficult than in example). I want to follow RAII principle and start/stop thid thread in constructor/destructor of base class.
The problem is, that calling virtual methods in constructor/destructor is a bad practice and didn't work in my case.
Here is a shot example of my problem:
#include <iostream>
#include <thread>
#include <atomic>
class Base {
public:
Base() {
bg_thread_ = std::thread([this] {
Open();
while(!is_stop_) {
// do stuff
}
Close();
});
}
~Base() {
is_stop_ = true;
if(bg_thread_.joinable()) {
bg_thread_.join();
}
}
private:
virtual void Open() {
std::cout << "Base open" << std::endl;
}
virtual void Close() {
std::cout << "Base close" << std::endl;
}
std::thread bg_thread_;
std::atomic<bool> is_stop_{false};
};
class Inherited : public Base {
virtual void Open() override {
std::cout << "Inherited open" << std::endl;
}
virtual void Close() override {
std::cout << "Inherited close" << std::endl;
}
};
int main() {
Inherited inherited;
std::this_thread::sleep_for(std::chrono::seconds(1));
return 0;
}
The output is:
Inherited open
Base close
And without sleep is:
Base open
Base close
My current approach is to call Start() method after constructor and Stop() before destructor, but I want solution with RAII.
void Start() {
bg_thread_ = std::thread([this] {
Open();
while(!is_stop_) {
// do stuff
}
Close();
});
}
void Stop() {
is_stop_ = true;
if(bg_thread_.joinable()) {
bg_thread_.join();
}
}
The problem is independent of threads. If you call virtual methods in the constructor of the Base, the Inherited object is not yet created so the Base implementations of the methods are called (or you get an error if they are pure virtual). If you call virtual methods in the destructor of Base the Inherited object is already destroyed so again the Base version of the virtual methods are called again.
Calling the methods from another thread does not change this behaviour. But the starting of the thread might take longer than the construction of the Inherited object so the object is fully constructed and the Inherited methods are called at the beginning of the worker thread.
One solution is to move the RAII to another object. So you don't call Start and Stop in Bases constructor and destructor. Then you can build a StartStopThing which takes a Base (by reference or by pointer) and calls Start and Stop in its constructor and destructor. Or you build a StartStopThing template class which takes Inherited as template argument, builds an Inherited object and calls the Start and Stop methods.

C++ Inheritance : Calling virtual method when it has been overridden

I am trying to build a service object which can run (i.e. execute it's run() function) in a separate thread. This is the service object
#include <boost/noncopyable.hpp>
#include <atomic>
#include <thread>
#include <iostream>
class service : public boost::noncopyable {
public:
service() : stop_(false), started_(false) { }
virtual ~service() {
stop();
if (thread_.joinable()) {
thread_.join();
}
}
virtual void stop() { stop_ = true; }
virtual void start() {
if (started_.load() == false) {
started_ = true;
thread_ = std::thread([&] () {
run();
});
}
}
protected:
virtual void run() = 0;
std::atomic<bool> stop_;
std::atomic<bool> started_;
std::thread thread_;
};
I am the creating a test class which inherits from this abstract class and is called in the main() function
class test : public service {
public:
test() : service() {
std::cout<< "CTOR" << std::endl;
start();
}
~test() {
std::cout<< "DTOR" << std::endl;
}
protected:
void run() override {
std::cout << "HELLO WORLD" <<std::endl;
}
};
int main() {
test test1;
return 0;
}
Now when I execute this, why do I get an error saying pure virtual function called? The run() function is clearly overridden in the test class. Whats worse is that it runs correctly sometimes?
$ ./a.out
CTOR
DTOR
pure virtual method called
terminate called without an active exception
$ ./a.out
CTOR
DTOR
pure virtual method called
terminate called without an active exception
$ ./a.out
CTOR
DTOR
pure virtual method called
terminate called without an active exception
$ ./a.out
CTOR
DTOR
HELLO WORLD
$ ./a.out
CTOR
DTOR
pure virtual method called
terminate called without an active exception
What could be going wrong here?
Follow along, step by step:
1) You construct the object.
2) You execute the following piece of code:
if (started_.load() == false) {
started_ = true;
thread_ = std::thread([&] () {
run();
});
}
The parent thread immediately returns to main() where it immediately exits and destroys your object.
Here's your bug:
You are not guaranteed that the thread started in start() is going to reach the call to run(), above, before the parent thread terminates the process. Both the child thread, and the parent thread runs concurrently.
So, every once in a while, the parent thread will destroy the object before the child thread gets in gear, and calls run().
At this point, the object whose run() method gets invoked, is already destroyed.
Undefined behavior.
The assertion you're hitting, every once in a while, is one possible result of this undefined behavior.

Using C++11 thread with pure virtual thread function

I have code where objects that are intended to execute in separate thread derive from a base class with a pure virtual Run function. I cannot get the following (simplified test code) to run the new thread.
#include <iostream>
#include <thread>
#include <functional>
class Base {
public:
virtual void Run() = 0;
void operator()() { Run(); }
};
class Derived : public Base {
public:
void Run() { std::cout << "Hello" << std::endl; }
};
void ThreadTest(Base& aBase) {
std::thread t(std::ref(aBase));
t.join();
}
int main(/*blah*/) {
Base* b = new Derived();
ThreadTest(*b);
}
The code compiles fine (which is half the battle) but "Hello" never gets printed. If I was doing something wrong I'd expect a runtime error at some point.
I'm using gcc.
Edit: The code above fails to compile on VS2012, with:
error C2064: term does not evaluate to a function taking 0 arguments
You need to use a lambda instead of std::ref, i.e.
void ThreadTest(Base& aBase)
{
std::thread t([&] ()
{
aBase.Run();
});
t.join();
}
You need to add -pthread to g++ command line, as explained in this answer to a similar question: https://stackoverflow.com/a/6485728/39622.