I'm working on a project that uses uses a thread to connect to a server. Whenever the login button is pressed, it initialized a thread to log in with the given IP and port provided by the user.
ServerPage.h
class ServerPage {
public:
static std::thread serverThread;
static void login();
}
ServerPage.cpp
#include "ServerPage.h"
std::thread ServerPage::serverThread;
void ServerPage::login() {
while (/*server is not connected*/) {
if (/*button is clicked and thread is not running*/)
serverThread = std::thread(Client::init, ip, port);
}
}
This works well until the button is clicked more than once. I'm able to use the Client class to see the status of the server (connected, not connected, or failure) Is there a way to delete or re initialize so that it can be run until the client is connected?
First of all: threads cannot be restarted. There is no such concept in programming. Unless by "restart" you mean "kill and spawn again".
It is not possible to kill a thread in a cross-platform way. For posix (I don't know about other OS) you can use pthreads (instead of std::thread) and send kill signal to it and spawn it again. But this is a ninja way, not necessarily what you should do. For example if you kill a thread that currently holds a lock, you will end up in a deadlock. This method should be avoided. However, if you can't modify Client::init method, then there might be no other choice without weakening your requirements.
A better solution is to pass around "cancellation tokens": small objects that you can register cancel handlers on it. Then you implement Client::init to cancel itself (and do any necessary cleanup, like releasing locks) whenever cancellation is triggered. Which you trigger on click.
Related
I 'm using boost beast 1.74.0. in another thread i try close the websocket but the code is broken at "acceptor.accept(socket, endpoint)" and i receive "Signal: SIG32 (Real-time event 32)" after call close.
Part from code to listen connection, What i need change to interrupt the accept correctly the service?
...
_acceptor = &acceptor;
_keepAlive = true;
while (_keepAlive) {
tcp::socket socket{ioc};
// Block until we get a connection
acceptor.accept(socket, endpoint);
// Launch the session, transferring ownership of the socket
std::thread(
&WebSocketServer::doSession,
std::move(socket),
this,
this,
getHeaderServer()
).detach();
}
close function call by another thread
void WebSocketServer::close() {
if (_acceptor != nullptr) this->close();
_keepAlive = false;
}
glibc uses SIG32 to signal the cancellation of threads created using the pthread library. Are you trying to use pthread_kill?
If not, you may be witnessing that only because you are running it under GDB. Which should be fixable by telling GDB to ignore that:
handle SIG32 nostop noprint
Finally to the original question:
there's interupption points in Boost Thread. They could help you iff you can switch to Boost Thread boost::thread instead of std::thread. Also, you have to change the thread's code to actually check for interruptions: https://www.boost.org/doc/libs/1_75_0/doc/html/thread/thread_management.html#thread.thread_management.tutorial.interruption
Since it actually sounds like you want to terminate the accept loop, why not "simply" cancel the acceptor? I'm not entirely sure this works with synchronous operations, but you could of course easily use an async accept.
Take care to synchronize access to the acceptor object itself. This means either run cancel on the same thread doing async_accept or from the same strand. By this point it surely sounds like it's easier to just do the whole thing asynchronously.
Introduction
Lets say I have an app with GUI, which gathers some data from the user and then call an embedded python script. I want to add "cancel button" in case the user want to stop the process.
Exemplary code
mainwindow
#include "calc_script.h"
signals:
void stopWorkSignal();
private:
calc_script *sender;
private slots:
Calculating()
on_pushButton_Cancel_clicked()
void MainWindow::Calculating()
{
QThread* newThread = new QThread();
connect(newThread, &QThread::started,
[=]() { sender->transfer(val_1, val_2, val_3); });
connect(this,
SIGNAL(stopWorkSignal()),
newThread,
SLOT(deleteLater())
newThread->start();
}
void MainWindow::on_pushButton_Cancel_clicked()
{
emit stopWorkSignal();
qDebug() << "stopwork signal emmitted";
}
calc_script.cpp
void calc_script::transfer(double val_1, double val_2, double val_3)
{
///Here the python (from boost.python) is executed
while(1) {}//this loop will generate a load to mimic this script, you cannot edit it, as the communication with .py is one-side at this lvl
}
The problem
When the signal is called I got the error QThread destroyed while thread is still running (and calculation seems to be still going). If I pass SLOT(quit()), nothing happens. If the calculation would be simple loop, I could pass a flag, to brake the loop. But due to calling python script I'm unable to do this, so I'm trying with destroying the Thread which hold the calculations. What's the correct way to do described functionality?
PS. I know I didn't included entire call to python but it is very long. For the reproduction error you can use any non-loop long calculations inside transfer function, it will do basically the same situation.
You can't forcibly terminate a thread; all you can do is ask it to quit, and then wait for it to exit of its own accord. (there does exist a QThread::terminate() method, but you shouldn't use it in production code, as it will cause problems: for example, if the thread had a mutex locked at the moment it got terminated, that mutex will remain locked forever, and your program will deadlock and freeze up the next time it attempts to lock that mutex).
So you have two options: either figure out a way to ask the Python thread to quit, or use a QProcess object (or something equivalent to it) to run the Python code in a child process instead of inside a thread. The benefit of running the Python code in a separate process is that you can safely kill() a child process -- since the child process doesn't share any state with your GUI process, and the OS will automatically clean up any resources allocated by the child process, there is no problem with the child process leaving mutexes locked or other resources un-freed.
If you'd rather ask the Python thread (or process) politely to exit instead of simply bringing down the hammer on it, you could do so via a networking interface; for example, you could create a TCP connection between your GUI code and the Python event loop, and the Python event loop could periodically do a non-blocking read on its end of the TCP connection. Then when your GUI wants the Python loop to exit, the GUI could close its TCP socket, and that would cause the Python loop's call to read() to return 0 (aka EOF), which the Python loop would know means "time to exit", so it could then exit voluntarily.
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.
I have an ordinary GUI Thread (Main Window) and want to attach a Worker thread to it. The Worker thread will be instantiated, moved to its own thread and then fired away to run on its own independently, running a messaging routine (non-blocking).
This is where the worker is created:
void MainWindow::on_connectButton_clicked()
{
Worker* workwork;
workwork= new Worker();
connect(workwork,SIGNAL(invokeTestResultsUpdate(int,quint8)),
this,SLOT(updateTestResults(int,quint8)),Qt::QueuedConnection);
connect(this,SIGNAL(emitInit()),workwork,SLOT(init()));
workwork->startBC();
}
This is where the Worker starts:
void Worker::startBC()
{
t1553 = new QThread();
this->moveToThread(t1553);
connect(t1553,SIGNAL(started()),this,SLOT(run1553Process()));
t1553->start();
}
I have two problems here, regarding the event queue of the new thread:
The first and minor problem is that, while I can receive the signals from the Worker thread (namely: invokeTestResultsUpdate), I cannot invoke the init method by emitting the emitInit signal from MainWindow. It just doesn't fire unless I call it directly or connect it via Qt::DirectConnection . Why is this happening? Because I have to start the Worker thread's own messaging loop explicitly? Or some other thing I'm not aware of? (I really fail to wrap my head around the concept of Thread/Event Loop/Signal Slot mechanism and the relation between each other even though I try. I welcome any fresh perspective here too.)
The second and more obscure problem is: run1553process method does some heavy work. By heavy work, I mean a very high rate of data. There is a loop running, and I try to receive the data flowing from a device (real-time) as soon as it lands in the buffer, using mostly extern API functions. Then throw the mentioned invokeTestResultsUpdate signal towards the GUI each time it receives a message, updating the message number box. It's nothing more than that.
The thing I'm experiencing is weird; normally the messaging routine is mostly unhindered but when I resize the main window, move it, or hide/show the window, the Worker thread skips many messages. And the resizing action is really slow (not responds very fast). It's really giving me a cancer.
(Note: I have tried subclassing QThread before, it did not mitigate the problem.)
I've been reading all the "Thread Affinity" topics and tried to apply them but it still behaves like it is somehow interrupted by the GUI thread's events at some point. I can understand MainWindow's troubles since there are many messages at the queue to be executed (both the invoked slots and the GUI events). But I cannot see as to why a background thread is affected by the GUI events. I really need to have an extremely robust and unhindered message routine running seperately behind, firing and forgetting the signals and not giving a damn about anything.
I'm really desperate for any help right now, so any bit of information is useful for me. Please do not hesitate to throw ideas.
TL;DR: call QCoreApplication::processEvents(); periodiacally inside run1553process.
Full explanation:
Signals from the main thread are put in a queue and executed once the event loop in the second thread takes control. In your implementation you call run1553Process as soon as the thread starts. the control will not go back to the event loop until the end of that function or QCoreApplication::processEvents is manually invoked so signals will just sit there waiting for the event loop to pick them up.
P.S.
you are leaking both the worker and the thread in the code above
P.P.S.
Data streams from devices normally provide an asynchronous API instead of you having to poll them indefinetly
I finally found the problem.
The crucial mistake was connecting the QThread's built in start() signal to run1553Process() slot. I had thought of this as replacing run() with this method, and expected everything to be fine. But this caused the actual run() method to get blocked, therefore preventing the event loop to start.
As stated in qthread.cpp:
void QThread::run()
{
(void) exec();
}
To fix this, I didn't touch the original start() signal, instead connected another signal to my run1553Process() independently. First started the thread ordinarily, allowed the event loop to start, then fired my other signals. That did it, now my Worker can receive all the messages.
I think now I understand the relation between threads and events better.
By the way, this solution did not take care of the message skipping problem entirely, but I feel that's caused by another factor (like my message reading implementation).
Thanks everyone for the ideas. I hope the solution helps some other poor guy like me.
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.