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.
Related
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.
I have some code that is to run on Linux (x86_64) and Raspberry Pi. The code runs ok on Linux, but crashes with a SIGSEGV on RPi. A derived method appears to not have the vtable populated and I wonder whether it is as a result of a race condition?
Here are the classes that implement the threading:
class Runnable {
public:
Runnable() {}
virtual ~Runnable() {}
// Starts the thread & execute the doWork() method.
void start() {
thread = std::thread(&Runnable::doWork, this);
}
// Stop the thread if running
virtual void stop() = 0;
// Joins the thread, blocks until the thread has finished.
void join() {
if (thread.joinable()) { thread.join(); }
}
protected:
std::thread thread; ///< the thread used by this class
/**
* #brief The method that does work. This will be called when the thread is started.
* The implementation should not return until stop() is called (or is finished with work).
* This is in protected scope as it should not be called except from the start() method.
*/
virtual void doWork() = 0;
};
template <typename VIRTUAL_CLASS_TYPE>
class SomeRunner : public Runnable {
public:
SomeRunner() {}
virtual ~SomeRunner() {
// do not delete classPtr, as a framework we are using deletes it for us
}
virtual void doWork() {
// do some work
classPtr = new VIRTUAL_CLASS_TYPE();
// notify main thread that we have created classPtr
// this is done via a condition variable & mutex
notifyIsReady();
// do some more work
}
virtual void stop() {
// tell thread to stop work
}
VIRTUAL_CLASS_TYPE *getClassPtr() {
return classPtr;
}
protected:
VIRTUAL_CLASS_TYPE *classPtr = nullptr;
}
// Within InterfaceLibrary.a
class BaseClass {
public:
BaseClass() {}
virtual ~BaseClass() {}
virtual void someMethod() = 0;
}
//Within ImplementationLibrary.a:
class ImplClass : public BaseClass {
public:
ImplClass() : BaseClass() {}
virtual ~ImplClass() {}
virtual void someMethod() {
// do something here
}
}
// within main application project
class ClassThatCausesDump {
// ...
void someMethod(BaseClass *bc) {
bc->someMethod();
}
}
bool isReady = false;
std::mutex mutexIsReady;
std::condition_variable cvIsReady;
void notifyGlsIsReady() {
std::unique_lock<std::mutex> lock(mutexIsReady);
isReady = true;
lock();
cvIsReady.notify_one();
}
int main(int argc, char **argv) {
// ...
SomeRunner<ImplClass> runner;
runner.start();
// main blocks until notified that the ImplClass has been created by runner
std::unique_lock<std::mutex> isReadyLock(mutexIsReady);
cvIsReady.wait(isReadyLock, [] {return isReady;});
ClassThatCausesDump dump;
dump.someMethod(runner.getClassPtr()); // this triggers the core dump on RPi
The variable classPtr, although passed as a BaseClass should call the derived someMethod(). However, when I run using gdb, I see that the program crashes at the call to someMethod() within ClassThatCausesDump. It tries to execute an instruction at 0x000000.
The program works on a Linux VM within a powerful multicore OSX machine, but not on RPi. I cleaned everything then recompiled, then it worked suddenly on RPi. Then I cleaned again to make sure it wasn't a fluke, then it went back to crashing (it never crashes on Linux). That makes me think there's perhaps something funny about the way the class is created in a separate thread perhaps?
Any ideas, please?
EDIT:
I don't think this is an issue to do with threading, because a call to the offending virtual function is ok if done within the doWork() method.
virtual void doWork() {
// do some work
classPtr = new VIRTUAL_CLASS_TYPE();
VIRTUAL_CLASS_TYPE *ptr = getClassPtr();
ptr->someMethod(); // this is ok and does not crash
// This next line is only here for testing because we know that VIRTUAL_CLASS_TYPE is of type ImplClass!
BaseClass *bc = (BaseClass*)ptr;
bc->someMethod(); // this crashes
// notify main thread that we have created classPtr
// this is done via a condition variable & mutex
notifyIsReady();
// do some more work
}
I'm looking to run a thread in a base class that constantly calls pure virtual method in that class that's overridden by a derived class.
For starting the thread, I've no issue as I can call an HasInitalized() function after it's been constructed. Therefore the thread is started after the class is fully constructed.
However, as the class' lifetime is managed by a shared_ptr, I cannot call a similar method for stopping the thread. If I stop the thread in the destructor, it will cause a seg-fault as the derived class is destroyed before the base and therefore will try to call a function that's not there.
I'm aware I can call a stop function from the derived class but would rather not have to on every instance of the derived class.
Is there a way around this.
Example:
#include "boost/thread.hpp"
class BaseClass
{
public:
BaseClass()
{
}
// Start the thread
void Start()
{
_thread = boost::thread(&BaseClass::ThreadLoop, this);
}
virtual ~BaseClass()
{
_thread.interrupt();
_thread.join();
}
private:
// Will loop until thread is interupted
void ThreadLoop()
{
try
{
while(true)
{
DoSomethingInDerivedClass();
boost::this_thread::interruption_point();
}
}
catch(...)
{
}
}
boost::thread _thread;
protected:
virtual void DoSomethingInDerivedClass() = 0;
};
class DerivedClass : public BaseClass
{
DerivedClass()
{
}
~DerivedClass()
{
// This gets called before base class destructor.
}
protected:
void DoSomethingInDerivedClass();
};
I don't think you will be able to avoid repeating the call to join the thread in the destructor of each derived class. If a thread depends on a non-static object o, then it's a good idea to have a clear ownership relation to guarantee the validity of the object:
The thread should own o and the destruction of o will be handled by the destructor of the thread object, after the joining.
o should own the thread and should join the thread in it's own destructor.
You've chosen the 2nd approach, except the thread depends on the derived object, but the derived object doesn't own the thread directly but through the sub-object (the base-object). Since the thread depends on the derived object, it must be joined in the derived object's destructor.
You should separate the two behaviours: a class to run and join the thread, the base class for the functional hierarchy.
class Runner {
public:
explicit Runner(std::shared_ptr<BaseClass> ptr) : m_ptr(ptr) {
m_thread = boost::thread(&Runner::ThreadLoop, this);
}
~Runner() {
m_thread.interrupt();
m_thread.join();
}
private:
void ThreadLoop() {
try {
while(true) {
m_ptr->DoSomethingInDerivedClass();
boost::this_thread::interruption_point();
}
} catch(...) {
}
}
std::shared_ptr<BaseClass> m_ptr;
std::thread m_thread;
};
My recommendation would be to use a weak_ptr to know when the object's lifetime is over:
The factory instantiates the (derived) object and stores it in a shared_ptr
The factory instantiates the watchdog class and passes it a weak_ptr to the new object
The watchdog thread can now check if the weak pointer is expired each time it needs to access it. When it is expired, the thread will terminate itself.
Here is an example (instead of a factory, I just used main):
#include <thread>
class BaseClass
{
public:
virtual ~BaseClass() = default;
virtual void DoSomethingInDerivedClass() = 0;
};
class DerivedClass : public BaseClass
{
public:
void DoSomethingInDerivedClass() override {}
};
// Will loop until weak_base expires
void ThreadLoop(std::weak_ptr<BaseClass> weak_base)
{
try
{
while (true)
{
std::shared_ptr<BaseClass> base = weak_base.lock();
if (base) {
base->DoSomethingInDerivedClass();
}
else {
break; // Base is gone. Terminate thread.
}
}
}
catch (...)
{
}
}
int main()
{
std::shared_ptr<DerivedClass> obj = std::make_shared<DerivedClass>();
std::thread([&] { ThreadLoop(obj); }).detach();
return 0;
}
Note that there is no need to explicitly stop the thread, since it will stop itself as soon as it detects that the object's lifetime is over. On the other hand, note that the thread may slightly outlive the lifetime of the being-watchted object, which could be considered bad design (it could e.g. defer program termination). I guess one could work around that by joining with the thread in the base class destructor, after signalling that it should terminate (if not already terminated).
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.)
I'm trying to use std::thread from C++11. I couldn't find anywhere if it is possible to have a std::thread inside a class executing one of its function members. Consider the example below...
In my try (below), the function is run().
I compile with gcc-4.4 with -std=c++0x flag.
#ifndef RUNNABLE_H
#define RUNNABLE_H
#include <thread>
class Runnable
{
public:
Runnable() : m_stop(false) {m_thread = std::thread(Runnable::run,this); }
virtual ~Runnable() { stop(); }
void stop() { m_stop = false; m_thread.join(); }
protected:
virtual void run() = 0;
bool m_stop;
private:
std::thread m_thread;
};
class myThread : public Runnable{
protected:
void run() { while(!m_stop){ /* do something... */ }; }
};
#endif // RUNNABLE_H
I'm getting this error and others: (same error with and without the $this)
Runnable.h|9|error: no matching function for call to ‘std::thread::thread(<unresolved overloaded function type>, Runnable* const)’|
When passing a pointer.
Runnable.h|9|error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ‘&Runnable::run’|
Here's some code to mull over:
#ifndef RUNNABLE_H
#define RUNNABLE_H
#include <atomic>
#include <thread>
class Runnable
{
public:
Runnable() : m_stop(), m_thread() { }
virtual ~Runnable() { try { stop(); } catch(...) { /*??*/ } }
Runnable(Runnable const&) = delete;
Runnable& operator =(Runnable const&) = delete;
void stop() { m_stop = true; m_thread.join(); }
void start() { m_thread = std::thread(&Runnable::run, this); }
protected:
virtual void run() = 0;
std::atomic<bool> m_stop;
private:
std::thread m_thread;
};
class myThread : public Runnable
{
protected:
void run() { while (!m_stop) { /* do something... */ }; }
};
#endif // RUNNABLE_H
Some notes:
Declaring m_stop as a simple bool as you were is horribly insufficient; read up on memory barriers
std::thread::join can throw so calling it without a try..catch from a destructor is reckless
std::thread and std::atomic<> are non-copyable, so Runnable should be marked as such, if for no other reason than to avoid C4512 warnings with VC++
That approach is wrong.
The problem is that while the object is still under construction its type is still not the most derived type, but the type of the constructor that is executing. That means that when you start the thread the object is still a Runnable and the call to run() can be dispatched to Runnable::run(), which is pure virtual, and that in turn will cause undefined behavior.
Even worse, you might run into a false sense of security, as it might be the case that under some circumstances the thread that is being started might take long enough for the current thread to complete the Runnable constructor, and enter the myThread object, in which case the new thread will execute the correct method, but change the system where you execute the program (different number of cores, or the load of the system, or any other unrelated circumstance) and the program will crash in production.