C++/QT Safely terminate a blocking thread - c++

I am creating an application, that communicates with a server using an API's functions, from an existing code base written in C++/Qt 5.6 and Boost. The code is written in a way such that, any communication with the server is done by the API's functions that runs in a worker object. The worker object runs in a QThread(), and is moved using moveToThread.
My problem is that, I need to be able to stop the thread immediately and disconnect in the situation where the network connection drops. However, the thread blocks when it sends data to the server. If I try to stop the thread through quit() or wait(), the request still goes through to the server which is undesirable. The API doesn't offer any method to cancel any ongoing requests either.
My current solution is terminating the thread, and destroying the worker object it owns when the network connection drops. I then create a new QThread and new worker object when connecting to the server.
I know that terminate() or any kind of immediate termination of a thread should be avoided like the plague but it seems to work I think.
The worker object that runs in the QThread uses std::shared_ptr for it's members through std::make_shared.
Are there still chances of memory leaks/corruption?
Apart from this, because I create my QThread in a method, I receive a warning from QT:
QObject: cannot create children for a parent that is in a different thread
Despite this warning, my code still runs but I have doubts. Is it safe to ignore this warning? What are the risks/consequences of ignoring this?
Is it safer to litter the server connecting code with QT's interruption checking points/rewrite it in boost using boost::interruption_point instead of calling terminate? i.e
sendData();
if (QThread::currentThread()->isInterruptionRequested())
{
return;
}
sendData();
if (QThread::currentThread()->isInterruptionRequested())
{
return;
}
...
Advice much appreciated thanks.

Related

How can I keep the Main thread from exiting until I receive a reply from a connected tcp socket?

Here is my context. MyApp exits normally by clicking on either the OK or the Cancel dialog button. MyApp also maintains a TCP connection to another app, HerApp. Before MyApp can normally exit by clicking on one of these buttons, it needs to inform HerApp that it is going offline. This advisory message is sent to HerApp via a socket defined using this derived class: class TxSocket : public CAsyncSocket. HerApps TCP listener replies which comes in on MyAppss TxSocket::OnReceive.
My problem is MyApp ends before the TCP OnReceive occurs.
I have thought of several approaches. Obviously, I cannot block the Main thread while the socket interaction completes because it too is running on the Main thread. I can’t let the Main thread go out of scope either because normal app exit in C++ means all its resources are cleaned up including resources used in any other threads (see cppreference Main function: “… destroys the objects with automatic storage duration…” ), so just launching another thread, which has automatic storage, merely to send the advisory message and wait for a receipt, is out of the question too. Statics are destroyed too so no help there. As a result, these techniques can’t be used either: use of std::thread in conjunction with std::packaged_task, the use of std::async or the setting and retrieving of std::promises and std::futures because the get_future object’s get() would block the Main thread too. I could create an intermediary thread that creates these flag objects, but again, they would all get prematurely destroyed on MyApps exit. The [What happens to a detached thread when main() exits?] (What happens to a detached thread when main() exits?) posting explores what happens when you detach a thread, but I found the answers to be non-definitive, at least for me as an app developer.
I need help finding a good and simple C++ approach to solving this synchronization problem which, I predict, will be quite common once we get past the Web HTML era.
Edit 1:
In order to clarify the context of my problem, here my MFC on cancel handler:
void MyAppDlg::OnCancel()
{
myApp->UseTcpioEngineToSendHerAppAdvisoryMsgThatMyAppHasCanceledExpectConfirmationReply(); // fails because connection and io objects get destroyed before completion
CDialog::OnCancel();
} // all automatic static etc storage is destroyed and exit is called

Qt Interface freeze on background task

I have an entertaining problem to solve. I use Qt 5 for one of my projects for reading information on the network. I read modbus devices and stuff, but the real problem comes when the network isn't available.
The interface freezes and I can't interact with it. The network stuff is done in a separate thread or that is what I think. Here is some code example:
class TwidoDevice : public QObject
{
Q_OBJECT
public:
explicit TwidoDevice
........ And some useful code
The use of the (main interface) class in Window.cpp is:
L1Thread = new QThread();
L1Thread->start();
L1TWD = new TwidoDevice(L1TWD_settings,
L1TWD_Name,
PercentRegisters,
TotalsRegisters,
db, 1);
L1TWD->moveToThread(L1Thread);
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()), Qt::DirectConnection);
In this code startFired() start reading the devices on the network.
In some other function in Window.cpp:
emit startReading()
When this code is executed the interface freezes even though I've moved the L1TWD object to QThread.
When I try to debug it using the built-in debugger in QtCreator, I can't seem to understand whether the object has been moved or not and why the interface is frozen during the network call.
Has any one encountered the same problem and what is the way to solve this?
Thank you for spending time reading my question!
This is the main problem:
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()), Qt::DirectConnection);
You are connecting the receiver and sender in different threads with direct connection, which will block the UI. Given that your slot execution gets stuck, this is expected. You have at least two issues here to solve.
Use the default connection which will not block across threads, just inside the same thread. So, you would be writing something like this:
connect(this, SIGNAL(startReading()), L1TWD, SLOT(startFired()));
Secondly, you could make sure that your thread does not get stuck when there is some "network" problem.
For debugging purposes, please print out the current thread when having this kind of threading issues using the following methods:
[static] QThread * QThread::​currentThread()
Returns a pointer to a QThread which manages the currently executing thread.
and this:
[static] Qt::HANDLE QThread::​currentThreadId()
Returns the thread handle of the currently executing thread.
Warning: The handle returned by this function is used for internal purposes and should not be used in any application code.
Warning: On Windows, the returned value is a pseudo-handle for the current thread. It can't be used for numerical comparison. i.e., this function returns the DWORD (Windows-Thread ID) returned by the Win32 function getCurrentThreadId(), not the HANDLE (Windows-Thread HANDLE) returned by the Win32 function getCurrentThread().
You are using a Qt::DirectConnection for your connection, which means the slot is called immediately, i.e on the same thread as the signal was fired. You can have a look at the documentation for ConnectionType. What you want to use is probably Qt::QueuedConnection, which executes the slot in the thread of the receiving object.
The best way though, as lpapp pointet out, is to let Qt decide what is best, and simply use Qt::AutoConnection, which is the default. It will use a QueuedConnection if signaling and receiving threads are different, and DirectConnection otherwise.

QThread doesn't start

Sorry for the length of this post. But I am stuck for two days now....
I am working on a Qt 4.6 Windows application that communicates with a hardware device through ActiveX.
When I send a command, the device does some stuff and when it's done (can take up to one minute) it emits a signal. I need to wait this signal to know if everything went okay (or not) and do some actions in consequence.
A command is sent to the device when a user clicks a button. And obviously, I don't want the HMI to freeze.
I am convinced I have to use threads. So I identified three threads:
the main thread corresponding to the HMI
the hardware controller (which locks after a command is sent and waits a signal)
a hardware notification listener that continuously gets signals from the hardware and unlock the thread 2
Here is the class diagram:
And a sequence diagram to show how I see things:
Explanations:
When the user launches my application, the HMI is created. The constructor of the HMI calls the constructor of the Worker. It constructs the hardware QAxObject. Then it constructs the HardwareListener giving in reference: the QAxObject, the QMutex and the QWaitCondition. Then the constructor of the Worker moves the HardwareListener object to another thread and starts it. Finally, the constructor of the HMI starts the thread of the Worker.
Then, when the user clicks a button, the HMI sends a signal to the Worker. The Worker sends a command to the hardware (that command may block the thread several seconds that's why I need the HardwareListener in another thread not to miss a signal). Then the Worker waits for a QWaitCondition (after having locked the QMutex).
After that, the hardware device sends a signal to the HardwareListener which wakes up the QWaitCondition. Therefore, the Worker thread stops waiting and finishes its actions. Finally, the Worker informs the HMI.
Problem:
The Worker and HardwareListener threads aren't created/started. Everything is done in the main thread so, obviously, it doesn't work. I don't exchange any special object between threads (so no need for qRegisterMetaType())
Question:
Is my design acceptable? There may be some other ways to do but it seems to me this is the most straightforward (taking into account the complexity).
EDIT:
I've changed my code to remove the QThread inheritance. I use the moveToThread() method instead.
Now the threads work fine. HOWEVER I have an ActiveX error: QAxBase: Error calling IDispatch member NewProject: Unknown error.
It seems the interfacing with the hardware is broken... Any idea?
Here is something interesting:
You cannot move a QAxObject to another thread once it has been created.
SOLUTION:
Here is what I have found.
Inheriting from QThread is not good design. If the work you are doing is computational heavy I would recommend using QThreadPool. I not than its better to use an asynchronous design. This means only calling function which never block and instead connect to signals notifying you that something happened.
So for example sending the command to the hardware and emitting a signal once the hardware is done. If the hardware API doesn't supply async functions than you are stuck with using threads.
QtConcurrentRun can help with that. Usually you should not need to touch threads yourself; and its a hell of a lot easier without.

Qt Socket blocking functions required to run in QThread where created. Any way past this?

The title is very cryptic, so here goes!
I am writing a client that behaves in a very synchronous manner. Due to the design of the protocol and the server, everything has to happen sequentially (send request, wait for reply, service reply etc.), so I am using blocking sockets. Here is where Qt comes in.
In my application I have a GUI thread, a command processing thread and a scripting engine thread. I create the QTcpSocket in the command processing thread, as part of my Client class. The Client class has various methods that boil down to writing to the socket, reading back a specific number of bytes, and returning a result.
The problem comes when I try to directly call Client methods from the scripting engine thread. The Qt sockets randomly time out and when using a debug build of Qt, I get these warnings:
QSocketNotifier: socket notifiers cannot be enabled from another thread
QSocketNotifier: socket notifiers cannot be disabled from another thread
Anytime I call these methods from the command processing thread (where Client was created), I do not get these problems.
To simply phrase the situation:
Calling blocking functions of QAbstractSocket, like waitForReadyRead(), from a thread other than the one where the socket was created (dynamically allocated), causes random behaviour and debug asserts/warnings.
Anyone else experienced this? Ways around it?
Thanks in advance.
I'm assuming that you're using QThread for the threading operations. If so, you can either a) use queued signal-slot connections; or b) explicitly use the QThread's event loop by creating a custom event type, posting that event in your scripting engine, and then having the client class handle those events.
example for a)
class ClientThread : public QThread
{
..stuff..
public slots:
waitForReadyRead();
};
class ScriptEngineThread : public QThread
{
..other stuff..
signals:
void requestWaitForReadyRead();
};
// In the ScriptEngineThread implementation...
ScriptEngineThread::setupClient()
{
connect(this, SIGNAL(requestWaitForReadyRead()),
client_, SLOT(waitForReadyRead()),
Qt::QueuedConnection);
}
Then, whenever you want to do the socket operations, just emit ScriptEngineThread::requestWaitForReadyRead();. The major difficulty is, I assume, you need the scripting thread to wait for some socket operation to be done. In this case you'll need to fire signals back and forth between the threads, causing some circular dependancy.
For alternative b, it would require a little more coding work, but you could:
Create your own subclasses of QEvent
Create a class to operate as a middleman, posting and handling each of your QEvents and emitting signals to communicate with the threads - each thread can have an instance of this
Connect the client and script engine to the event signals it cares about.

boost::asio, threads and synchronization

This is somewhat related to this question, but I think I need to know a little bit more. I've been trying to get my head around how to do this for a few days (whilst working on other parts), but the time has come for me to bite the bullet and get multi-threaded. Also, I'm after a bit more information than the question linked.
Firstly, about multi-threading. As I have been testing my code, I've not bothered with any multi-threading. It's just a console application that starts a connection to a test server and everything else is then handled. The main loop is this:
while(true)
{
Root::instance().performIO(); // calls io_service::runOne();
}
When I write my main application, I'm guessing this solution won't be acceptable (as it would have to be called in the message loop which, whilst possible, would have issues when the message queue blocks waiting for a message. You could change it so that the message-loop doesn't block, but then isn't that going to whack the CPU usage through the roof?)
The solution it seems is to throw another thread at it. Okay, fine. But then I've read that io_service::run() returns when there is no work to do. What is that? Is that when there's no data, or no connections? If at least one connection exists does it stay alive? If so, that's not so much of a problem as I only have to start up a new thread when the first connection is made and I'm happy if it all stops when there is nothing going on at all. I guess I am confused by the definition of 'no work to do'.
Then I have to worry about synchronizing my boost thread with my main GUI thread. So, I guess my questions are:
What is the best-practice way of using boost::asio in a client application with regard to threads and keeping them alive?
When writing to a socket from the main thread to the IO thread, is synchronization achieved using boost::asio::post, so that the call happens later in the io_service?
When data is received, how do people get the data back to the UI thread? In the past when I used completion ports, I made a special event that could post the data back to the main UI thread using a ::SendMessage. It wasn't elegant, but it worked.
I'll be reading some more today, but it would be great to get a heads up from someone who has done this already. The Boost::asio documentation isn't great, and most of my work so far has been based on a bit of the documentation, some trial/error, some example code on the web.
1) Have a look at io_service::work. As long as an work object exists io_service::run will not return. So if you start doing your clean up, destroy the work object, cancel any outstanding operations, for example an async_read on a socket, wait for run to return and clean up your resources.
2) io_service::post will asynchronously execute the given handler from a thread running the io_service. A callback can be used to get the result of the operation executed.
3) You needs some form of messaging system to inform your GUI thread of the new data. There are several possibilities here.
As far as your remark about the documention, I thing Asio is one of the better documented boost libraries and it comes with clear examples.
boost::io_service::run() will return only when there's nothing to do, so no async operations are pending, e.g. async accept/connection, async read/write or async timer wait. so before calling io_service::run() you first have to start any async op.
i haven't got do you have console or GUI app? in any case multithreading looks like a overkill. you can use Asio in conjunction with your message loop. if it's win32 GUI you can call io_service::run_one() from you OnIdle() handler. in case of console application you can setup deadline_timer that regularly checks (every 200ms?) for user input and use it with io_service::run(). everything in single thread to greatly simplify the solution
1) What is the best-practice way of using
boost::asio in a client application
with regard to threads and keeping
them alive?
As the documentation suggests, a pool of threads invoking io_service::run is the most scalable and easiest to implement.
2) When writing to a socket from the main
thread to the IO thread, is
synchronization achieved using
boost::asio::post, so that the call
happens later in the io_service?
You will need to use a strand to protect any handlers that can be invoked by multiple threads. See this answer as it may help you, as well as this example.
3) When data is received, how do people
get the data back to the UI thread? In
the past when I used completion ports,
I made a special event that could post
the data back to the main UI thread
using a ::SendMessage. It wasn't
elegant, but it worked.
How about providing a callback in the form of a boost::function when you post an asynchronous event to the io_service? Then the event's handler can invoke the callback and update the UI with the results.
When data is received, how do people get the data back to the UI thread? In the past when I used completion ports, I made a special event that could post the data back to the main UI thread using a ::SendMessage. It wasn't elegant, but it worked
::PostMessage may be more appropriate.
Unless everything runs in one thread these mechanisms must be used to safely post events to the UI thread.