How to "try_lock" a recursive mutex to avoid crashes during destruction - c++

I have a class that continuously makes rest calls with the use of a timer, the result of these rest calls gets sent back into the class and is processed afterwards.
The problem is, if this class's destructor gets called while this update process is going on this causes a crash.
I attempted to solve this with the use of a recursive mutex;
private:
QTimer* m_Timer = nullptr;
std::recursive_mutex m_RecursiveMutex;
Placing one lock call on the destructor and a try_lock the start of the update function;
Class::~Destructor()
{
std::lock_guard<std::recursive_mutex> lock(m_RecursiveMutex);
m_Timer->stop();
delete m_Timer;
}
void Class::UpdateSelf(GetInfoResponse res)
{
if (m_RecursiveMutex.try_lock())
{
... do stuff
}
}
However this doesn't seem to change anything as the update function still gets called and crashes the program, I have no idea what I'm doing wrong so I'd appreciate any input.

Related

Waiting in the UI thread but the function to set end condition is called in the UI thread

I have a function foo that is called in the UI thread. Inside it, I call functionA whose return value will determine whether I call functionB or not. Inside functionA, I call funcFromAnotherProject which actually runs in a worker thread. I need to wait for this to end before I can proceed with functionC.
void foo() {
bool succeeded = functionA();
if (succeeded) functionB();
}
bool functionA() {
if (someCondition) {
funcFromAnotherProject();
}
return functionC();
}
Fortunately, funcFromAnotherProject can accept a callback parameter so I can actually pass functionC as a callback so the order is preserved. However, if I do this, I won't be able to get functionC's return value which I need in foo.
I then decided to do the following (the bool variable is actually a shared pointer to a class that wraps around a HANDLE but it's too complicated):
bool functionA() {
bool finishedFuncFromAnotherProject = false;
auto callback = [&finishedFuncFromAnotherProject](){
finishedFuncFromAnotherProject = true;
};
if (someCondition) {
funcFromAnotherProject(callback);
waitUntilAboveFuncFinishes();
}
return functionC();
}
The problem with this is that I am calling wait in the UI thread and funcFromAnotherProject calls the callback in the UI thread as well. The callback is never called because the wait is blocking everything else.
Running foo in the worker thread will solve the above problem, however I need to block the UI thread until functionB finishes.
funcFromAnotherProject will always run in a worker thread so I can't change that. If it comes down to it, what I can do is add a flag for funcFromAnotherProject on whether it should run the callback in the UI thread or not. But since this is a utility in our program, I'd rather not touch it.
Is there another way to go about this? I feel like this should be very simple and I'm just overthinking things.

How to properly delete a pointer to callback function.

I have a MainProgram.exe which calls in to MyDll.dll and uses curl to receive data on a callback function.
I have wrapped curl in a function called CurlGetData which creates a curl instance and performs curl_easy_perform.
Here is my code:
//Interface class to derive from
class ICurlCallbackHandler
{
public:
virtual size_t CurlDataCallback( void* pData, size_t tSize ) = 0;
};
//Class that implements interface
class CurlCallbackHandler : public ICurlCallbackHandler
{
public:
bool m_exit = false;
virtual size_t CurlDataCallback( void* pData, size_t tSize ) override
{
if(m_exit)
return CURL_READFUNC_ABORT;
// do stuff with the curl data
return tSize;
}
}
CurlCallbackHandler *m_curlHandler;
//Create an instance of above class in my dll constructor
MyDll:MyDll()
{
m_curlHandler = new CurlCallbackHandler();
}
//Cleanup above class in my dll destructor
MyDll:~MyDll()
{
delete m_curlHandler;
m_curlHandler = nullptr;
}
//Function to start receiving data asynchronously
void MyDll::GetDataAsync()
{
std::async([=]
{
//This will receive data in a new thread and call CurlDataCallback above
//This basically calls easy_perform
CurlGetData(m_curlHandler);
}
}
//Will cause the curl callback to return CURL_READFUNC_ABORT
void MyDll::StopDataAsync()
{
m_curlHandler->m_exit = true;
}
The function GetDataAsync is called from my main program and it basically calls curl_easy_perform and uses the m_curlHandler as its callback function which calls back up into CurlDataCallback.
This all works fine but whenever my main program exits, it calls MyDll::StopDataAsync which stops the curl data callback and then the destructor of MyDll is called which cleans up the m_curlHandler.
But I find that at that moment curl has not yet finished with this call back and the program crashes as m_curlHandler has been deleted but the curl callback in the new async thread still is using it.
Sometimes it closes down fine but other times it crashes due to the curlcallback trying to access a pointer that has been deleted by the destructor.
How can I best clean up the m_curlHandler? I want to avoid putting in wait time-outs as this this will affect the performance of my main program.
According to the C++ standard the MyDll::GetDataAsync() function should not return immediately, it should block until the asynchronous thread has finished, which would effectively make the operation synchronous. However I believe Microsoft intentionally violated this part of the std::async specification, so actually it does return immediately, and it's possible for you to destroy the callback while the async thread is still using it (which is exactly the problem that would be avoided if the Microsoft implementation followed the standard!)
The solution is to keep hold of the std::future that std::async returns, and then block on that future (which ensures the async thread has finished) before destroying the callback.
class MyDLL
{
std::future<void> m_future;
...
};
MyDll:~MyDll()
{
StopDataAsync();
m_future.get(); // wait for async thread to exit.
delete m_curlHandler; // now it's safe to do this
}
//Function to start receiving data asynchronously
void MyDll::GetDataAsync()
{
m_future = std::async([=]
{
//This will receive data in a new thread and call CurlDataCallback above
//This basically calls easy_perform
CurlGetData(m_curlHandler);
}
}
N.B. your m_exit member should be std::atomic<bool> (or you should use a mutex to protect all reads and writes to it) otherwise your program has a data race and so has undefined behaviour.
I would also use std::unique_ptr<CurlCallbackHandler> for m_curlHandler.
I want to avoid putting in wait time-outs as this this will affect the performance of my main program.
The solution above will cause your destructor to wait, but only for as long as it takes for the callback to notice that m_exit == true and cause the async thread to stop running. That means you only wait as long as necessary and no longer, unlike time-outs which would mean guessing how long is "long enough", and then probably adding a bit more to be safe.

Best way to handle multi-thread cleanup

I have a server-type application, and I have an issue with making sure thread's aren't deleted before they complete. The code below pretty much represents my server; the cleanup is required to prevent a build up of dead threads in the list.
using namespace std;
class A {
public:
void doSomethingThreaded(function<void()> cleanupFunction, function<bool()> getStopFlag) {
somethingThread = thread([cleanupFunction, getStopFlag, this]() {
doSomething(getStopFlag);
cleanupFunction();
});
}
private:
void doSomething(function<bool()> getStopFlag);
thread somethingThread;
...
}
class B {
public:
void runServer();
void stop() {
stopFlag = true;
waitForListToBeEmpty();
}
private:
void waitForListToBeEmpty() { ... };
void handleAccept(...) {
shared_ptr<A> newClient(new A());
{
unique_lock<mutex> lock(listMutex);
clientData.push_back(newClient);
}
newClient.doSomethingThreaded(bind(&B::cleanup, this, newClient), [this]() {
return stopFlag;
});
}
void cleanup(shared_ptr<A> data) {
unique_lock<mutex> lock(listMutex);
clientData.remove(data);
}
list<shared_ptr<A>> clientData;
mutex listMutex;
atomc<bool> stopFlag;
}
The issue seems to be that the destructors run in the wrong order - i.e. the shared_ptr is destructed at when the thread's function completes, meaning the 'A' object is deleted before thread completion, causing havok when the thread's destructor is called.
i.e.
Call cleanup function
All references to this (i.e. an A object) removed, so call destructor (including this thread's destructor)
Call this thread's destructor again -- OH NOES!
I've looked at alternatives, such as maintaining a 'to be removed' list which is periodically used to clean the primary list by another thread, or using a time-delayed deletor function for the shared pointers, but both of these seem abit chunky and could have race conditions.
Anyone know of a good way to do this? I can't see an easy way of refactoring it to work ok.
Are the threads joinable or detached? I don't see any detach,
which means that destructing the thread object without having
joined it is a fatal error. You might try simply detaching it,
although this can make a clean shutdown somewhat complex. (Of
course, for a lot of servers, there should never be a shutdown
anyway.) Otherwise: what I've done in the past is to create
a reaper thread; a thread which does nothing but join any
outstanding threads, to clean up after them.
I might add that this is a good example of a case where
shared_ptr is not appropriate. You want full control over
when the delete occurs; if you detach, you can do it in the
clean up function (but quite frankly, just using delete this;
at the end of the lambda in A::doSomethingThreaded seems more
readable); otherwise, you do it after you've joined, in the
reaper thread.
EDIT:
For the reaper thread, something like the following should work:
class ReaperQueue
{
std::deque<A*> myQueue;
std::mutex myMutex;
std::conditional_variable myCond;
A* getOne()
{
std::lock<std::mutex> lock( myMutex );
myCond.wait( lock, [&]( !myQueue.empty() ) );
A* results = myQueue.front();
myQueue.pop_front();
return results;
}
public:
void readyToReap( A* finished_thread )
{
std::unique_lock<std::mutex> lock( myMutex );
myQueue.push_back( finished_thread );
myCond.notify_all();
}
void reaperThread()
{
for ( ; ; )
{
A* mine = getOne();
mine->somethingThread.join();
delete mine;
}
}
};
(Warning: I've not tested this, and I've tried to use the C++11
functionality. I've only actually implemented it, in the past,
using pthreads, so there could be some errors. The basic
principles should hold, however.)
To use, create an instance, then start a thread calling
reaperThread on it. In the cleanup of each thread, call
readyToReap.
To support a clean shutdown, you may want to use two queues: you
insert each thread into the first, as it is created, and then
move it from the first to the second (which would correspond to
myQueue, above) in readyToReap. To shut down, you then wait
until both queues are empty (not starting any new threads in
this interval, of course).
The issue is that, since you manage A via shared pointers, the this pointer captured by the thread lambda really needs to be a shared pointer rather than a raw pointer to prevent it from becoming dangling. The problem is that there's no easy way to create a shared_ptr from a raw pointer when you don't have an actual shared_ptr as well.
One way to get around this is to use shared_from_this:
class A : public enable_shared_from_this<A> {
public:
void doSomethingThreaded(function<void()> cleanupFunction, function<bool()> getStopFlag) {
somethingThread = thread([cleanupFunction, getStopFlag, this]() {
shared_ptr<A> temp = shared_from_this();
doSomething(getStopFlag);
cleanupFunction();
});
this creates an extra shared_ptr to the A object that keeps it alive until the thread finishes.
Note that you still have the problem with join/detach that James Kanze identified -- Every thread must have either join or detach called on it exactly once before it is destroyed. You can fulfill that requirement by adding a detach call to the thread lambda if you never care about the thread exit value.
You also have potential for problems if doSomethingThreaded is called multiple times on a single A object...
For those who are interested, I took abit of both answers given (i.e. James' detach suggestion, and Chris' suggestion about shared_ptr's).
My resultant code looks like this and seems neater and doesn't cause a crash on shutdown or client disconnect:
using namespace std;
class A {
public:
void doSomething(function<bool()> getStopFlag) {
...
}
private:
...
}
class B {
public:
void runServer();
void stop() {
stopFlag = true;
waitForListToBeEmpty();
}
private:
void waitForListToBeEmpty() { ... };
void handleAccept(...) {
shared_ptr<A> newClient(new A());
{
unique_lock<mutex> lock(listMutex);
clientData.push_back(newClient);
}
thread clientThread([this, newClient]() {
// Capture the shared_ptr until thread over and done with.
newClient->doSomething([this]() {
return stopFlag;
});
cleanup(newClient);
});
// Detach to remove the need to store these threads until their completion.
clientThread.detach();
}
void cleanup(shared_ptr<A> data) {
unique_lock<mutex> lock(listMutex);
clientData.remove(data);
}
list<shared_ptr<A>> clientData; // Can remove this if you don't
// need to connect with your clients.
// However, you'd need to make sure this
// didn't get deallocated before all clients
// finished as they reference the boolean stopFlag
// OR make it a shared_ptr to an atomic boolean
mutex listMutex;
atomc<bool> stopFlag;
}

Waiting for an asynchronous method to finish

In my multi-threaded programs I often use an approach like shown below to synchronize access to data:
class MyAsyncClass
{
public: // public thread safe interface of MyAsyncClass
void start()
{
// add work to io_service
_ioServiceWork.reset(new boost::asio::io_service::work(_ioService));
// start io service
_ioServiceThread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&boost::asio::io_service::run, &_ioService)));
}
void stop()
{
_ioService.post(boost::bind(&MyAsyncClass::stop_internal, this));
// QUESTION:
// how do I wait for stop_internal to finish here?
// remove work
_ioServiceWork.reset();
// wait for the io_service to return from run()
if (_ioServiceThread && _ioServiceThread->joinable())
_ioServiceThread->join();
// allow subsequent calls to run()
_ioService.reset();
// delete thread
_ioServiceThread.reset();
}
void doSometing()
{
_ioService.post(boost::bind(&MyAsyncClass::doSometing_internal, this));
}
private: // internal handlers
void stop_internal()
{
_myMember = 0;
}
void doSomething_internal()
{
_myMember++;
}
private: // private variables
// io service and its thread
boost::asio::io_service _ioService;
boost::shared_ptr<boost::thread> _ioServiceThread;
// work object to prevent io service from running out of work
std::unique_ptr<boost::asio::io_service::work> _ioServiceWork;
// some member that should be modified only from _ioServiceThread
int _myMember;
};
The public interface of this class is thread-safe in the sense that its public methods can be called from any thread and boost::asio::io_service takes care that access to the private members of this class are synchronized. Therefore the public doSomething() does nothing but posting the actual work into the io_service.
The start() and stop() methods of MyAsyncClass obviously start and stop processing in MyAsyncClass. I want to be able to call MyAsyncClass::stop() from any thread and it should not return before the uninitialization of MyAsyncClass has finished.
Since in this particular case I need to modify one of my private members (that needs synchronized access) when stopping, I introduced a stop_internal() method which I post to the io_service from stop().
Now the question is: How can I wait for the execution of stop_internal() to finish inside stop()? Note that I cannot call stop_internal() directly because it would run in the wrong thread.
Edit:
It would be nice to have a solution that also works if MyAsyncClass::stop() is called from the _ioServiceThread, so that MyAsyncClass can also stop itself.
I just found a very nice solution myself:
Instead of removing work (resetting _ioServiceWork) in stop(), I do it at the end of stop_internal(). This means that _ioServiceThread->join() blocks until stop_internal() has finished - exactly what I want.
The nice thing about this solution is that it doesn't need any mutex or condition variable or stuff like this.

How can I protect a QThread function so it will not be called again until finished its previous work?

I'm using a QThread and inside its run method I have a timer invoking a function that performs some heavy actions that take some time. Usually more than the interval that triggers the timer (but not always).
What I need is to protect this method so it can be invoked only if it has completed its previous job.
Here is the code:
NotificationThread::NotificationThread(QObject *parent)
: QThread(parent),
bWorking(false),
m_timerInterval(0)
{
}
NotificationThread::~NotificationThread()
{
;
}
void NotificationThread::fire()
{
if (!bWorking)
{
m_mutex.lock(); // <-- This is not protection the GetUpdateTime method from invoking over and over.
bWorking = true;
int size = groupsMarkedForUpdate.size();
if (MyApp::getInstance()->GetUpdateTime(batchVectorResult))
{
bWorking = false;
emit UpdateNotifications();
}
m_mutex.unlock();
}
}
void NotificationThread::run()
{
m_NotificationTimer = new QTimer();
connect(m_NotificationTimer,
SIGNAL(timeout()),
this,
SLOT(fire(),
Qt::DirectConnection));
int interval = val.toInt();
m_NotificationTimer->setInterval(3000);
m_NotificationTimer->start();
QThread::exec();
}
// This method is invoked from the main class
void NotificationThread::Execute(const QStringList batchReqList)
{
m_batchReqList = batchReqList;
start();
}
You could always have a thread that needs to run the method connected to an onDone signal that alerts all subscribers that it is complete. Then you should not run into the problems associated with double lock check and memory reordering. Maintain the run state in each thread.
I'm assuming you want to protect your thread from calls from another thread. Am I right? If yes, then..
This is what QMutex is for. QMutex gives you an interface to "lock" the thread until it is "unlocked", thus serializing access to the thread. You can choose to unlock the thread until it is done doing its work. But use it at your own risk. QMutex presents its own problems when used incorrectly. Refer to the documentation for more information on this.
But there are many more ways to solve your problem, like for example, #Beached suggests a simpler way to solve the problem; your instance of QThread would emit a signal if it's done. Or better yet, make a bool isDone inside your thread which would then be true if it's done, or false if it's not. If ever it's true then it's safe to call the method. But make sure you do not manipulate isDone outside the thread that owns it. I suggest you only manipulate isDone inside your QThread.
Here's the class documentation: link
LOL, I seriously misinterpreted your question. Sorry. It seems you've already done my second suggestion with bWorking.