I have the message "QWaitCondition: Destroyed while threads are still waiting" following the launch of N threads in a loop, and waiting for each in another loop.
Here is the code :
int nb_threads = QThread::idealThreadCount();
QFuture<void> futures[nb_threads];
bool shared_boolean;
// launch threads
for(int i = 0;i<nb_threads;++i){
futures[i] = QtConcurrent::run(this,gpMainLoopMT,&shared_boolean,&next_pop_size,next_population);
}
// wait for threads to finish
for(int i = 0;i<nb_threads;++i){
futures[i].waitForFinished();
}
I just can't figure out why this is happening, while I am waiting for each thread.
Actually I had the same warning when using Qt in a DLL. Windows kills all threads at application exit, before the DLL's global objects are destroyed. A global object destructor is where I was deleting the QApplication instance. This leads to an inconsistency because the QWaitConditions still think a thread is waiting, when in fact the native thread isn't running anymore, killed by Windows with no chance of proper cleanup. That's what leads to this warning.
It's unfixable, even in Qt. Windows doesn't give us any chance to perform any cleanup, the threads just disappear.
You're not waiting for the threads, you're waiting for the tasks.
The threads keep running until QApplication deletes the global QThreadPool instance. So the question is - are you leaking QApplication or destroying it properly?
Related
For example:
void MainWidget::testThreadTask()
{
qDebug() << "On test task";
}
void MainWidget::onBtnClick()
{
QThread *thread = new QThread;
connect(thread, QThread::started, this, testThreadTask);
thread->start();
qDebug() << "Thread START, now we wait 5s";
QElapsedTimer timer;
timer.start();
while (timer.elapsed() < 5000)
{
}
qDebug() << "END";
}
The program output is:
START wait 5s
END
On test task
I want to create a task to handle something after the button is pressed, and then the function will wait for the task to complete before returning.
In fact, it may not be necessary to create a new task and wait for it to execute, because since you have to wait and get stuck there, why not run it directly in the function.
But this is actually a problem when I deal with QT serial data. I want to send the data to the serial port after pressing the button, and then wait for the data (by constantly reading), but I find that when I have been waiting, the serial port can not read the data at all, only when I exit the function the serial port can read the data.
Is there any way to deal with serial data sending and receiving synchronization?
void MainWidget::onBtnClick()
{
serial->write("Test");
if (serial->bytesAvailable())
{
QByteArray data = serialIo->readAll();
// handle the data
}
}
You are mistaken with what is happening in your application. I suggest you read Threads and QObjects (the entire page), Qt::ConnectionType and the detailed description of QThread.
What is happening to you is:
MainWidget does not live in thread. For the slot of a regular object to be called from thread, it first needs to be moved to that thread.Note that subclasses of QWidget cannot be moved to another thread. Because some OS supported by Qt limit where windows can live, they made the choice to force all QWidget to stay in the main thread, in all OS Qt can execute on.
When you connect thread to this (which BTW is incorrect in your question, it should have been with ampersands connect(thread, &QThread::started, this, &MainWidget::testThreadTask);), you create a queued connection, even though the thread has not technically started yet.
When you start the thread:
It fires its started signal.
Because the connection is a Qt::QueuedConnection, the slot will only be executed after returning to the main thread's event loop, i.e. some time after returning from onBtnClick.
Notes:
You would have more useful information in qDebug() about the threads running your code by using QThread::currentThread().Even better than that, your IDE should provide you a window specifically to see what thread has reached a breakpoint (Ctrl+Alt+H on Visual Studio).
At the risk of insisting, keep in mind this warning from the Qt help:
Be aware that using direct connections when the sender and receiver live in different threads is unsafe if an event loop is running in the receiver's thread, for the same reason that calling any function on an object living in another thread is unsafe.
With that said, because you wait 5 seconds before returning to the event loop and because it is only test code (= there should be no bug + it does not matter even if there is one), you should try to create a Qt::DirectConnection, just to see the slot be invoked from the worker thread.
The detailed description of QThread (link above) shows a complete working example of a worker object being moved to the new thread before it is started. The point is:
A worker object is created, then moved to the worker thread.
Connections are created for the controller to send QString to the worker object via signal/slot and for the worker object to return result to the controller via signal/slot too.
All these connections are Qt::QueuedConnection by default since the worker object was moved.
The worker thread is started. Since run was not overriden, it starts an event loop (in exec).
And there you have it.
Remember 1 things: widgets cannot be moved!!! Create your own worker object.
How can I define a barrier point In a Qthread run() method for synchronization.
My run method code consists of two stages, and all of the threads must reach the end of the first stage before they can pass the second stage.
void ThreadClass::run()
{
barrier// All of the thread must reach this point before passing below the line
}
From the top of my head ::
1 : Create a mutex and then lock it in your main() before creating the thread pool. Create the thread pool, let them run, your barrier should read like this.
perThreadReachedThisPointFlag = 1;
mutexCreatedByMain.lock();
mutexCreatedByMain.unlock();
In your main(), monitor the thread pool. If you observe (do not forget the memory fences) that all the threads in the pool have set the perThreadReachedThisPointFlag, then execute mutexCreatedByMain.unlock(); on your main().
All the threads were waiting to lock the mentioned mutex, then you let them go. All of them will lock then unlock the mutex.
2 : Another way would be using conditionVariable and conditionSignal functionality of pthread but I do not know a replacement for Windows.
I need to detect the application get exit as normal or crash. QProcess have the finished() signal and can get the exit code. But i need this exit code for QApplication when the application get crash or close.
When your process crashes, it's gone. The crash means that the process has finished because of an unhandled exception. Your job should be to prevent the crash from happening. In other words: handle the exceptions. Note that the exceptions may not be C++ exceptions, they may be low-level platform-specific mechanisms, such as native exceptions on Windows or signals on UNIX. You'd have to handle those, but recognize that the underlying issue is not fixed merely because you catch such an exception. You must assume that the state of your application has been corrupted, and the only safe thing to do is to exit ASAP anyway. For example, do not try to modify any files: you're likely to corrupt them.
I don't think this is something you can do just like that. Reading the value returned by QApplication::exec() is related to the Qt infrastructure:
Enters the main event loop and waits until exit() is called, then
returns the value that was set to exit() (which is 0 if exit() is
called via quit()).
Usually your main looks like this:
#include <QApplication>
int main( int argc, char **argv )
{
QApplication a( argc, argv );
// Initialize your widget(s)
return a.exec(); // You can store this and check its value
}
However if I'm not mistaken this doesn't include handling a crash of your application (segmentation fault, unhandled exception etc.). In Linux people usually use a script which starts the application and then reads its exit code after the application quits or crashes. If you use Linux you can use echo $? to read the exit code from the bash scrip (or its equivalent for a different shell) and then do something based on its value.
Note also that you can at least do some exception handling since some crashes result in exactly that - an exception that has been thrown for some reason and has not been processed properly. Unhandled exceptions in Qt get propagated to the top level (that is QCoreApplication).
Brief of environment:
I have a device on which runs an application written in qt. It has a main thread which handles Database operations (SQlite) and a separate thread for networking operations (via 3G).
Mains thread Event loop is ran by QCoreApplication::exec and the other thread which handles networking operations is ran by QThread::exec. Btw, socket thread affinity is changed after it's started (Eg. moveToThread(socketThreadPtr))
Brief of problem:
Main thread is busy in a loop, in order to select around 10k records from database and that loop takes about +30 seconds. In the network thread there is a 15 seconds timer which has to send a keep alive message each time expires. The problem is that the slot for timeout() signal is executed only after the loop is finished.
Solution founded until now(but not satisfying):
If I call QCoreApplication::processEvents in the loop that selects the records, problem is solved, but I wonder if a solution exists instead of this workaround.
Remark:
The timer, signal and slot, which gives the command to send the keep alive message is currently handled in the main thread( but the read/write happens in the network thread). Also, I moved the timer on the network thread but I got the same result as being on the main thread.
You have to create timer in your network thread, maybe Qtimer is a member of network thread, so the network thread will be constructed in main thread and thread affinity of its children's
set to main thread, next you have moved network thread to new Qthread, but what about Qtimer? it still lives in main thread (except when you explicitly define network class as it's parent, so as you said moveToThread will affect object's children as well as Qtimer)
The Qtimer should be constructed in network thread, you can construct a new Qtimer in one of the network thread slots and connecting it to the Qthread::start signal. So by calling start method of Qthrad your slot will be executed on new thread and Qtimer will be constructed on that thread respectively.
Something like this should actually create the socket and the timer in your dedicated thread, given your main-thread is the server and clients should be handled in threads. Otherwise just use QTcpSocket::connectToHost() or QTcpServer:::bind()in your initialize function.
Mainthread:
auto t = new QThread();
t->start();
auto o = new MyThreadObject();
o.moveToThread(t);
o.setDescriptor(socketDesc);
QMetaObject::invokeMethod(o, "initialize", Qt::QueuedConnection);
MyThreadObject:
class MyThreadObject : public QObject
{
Q_OBJECT
public:
MyThreadObject(){...};
void setDescriptor(qintptr socketdescriptor)
{
m_desc = socketdescriptor;
}
public slots:
void initialize()
{
m_tcpSocket = new QTcpSocket();
m_tcpSocket->setSocketDescriptor(m_desc);
//socket configuration
m_timer = new QTimer();
//timer configuration
m_timer->start();
}
private:
QTcpSocket* m_tcpSocket;
QTimer* m_timer;
qintptr m_desc;
}
I am developing an application on Qt symbian, in which I have to restart my application within my application, have used:
qApp->quit();
QProcess::startDetached(qApp->arguments()[0],qApp->arguments());
from a method in mainWindow. It is working fine on simulator but not on device, it closes but not restarting by itself, I have to restart it by myself, is there anything else I have to do to make it work on device.
One solution would be to create small console process that you can launch from your main program before closing it. Then this console process would just launch your program and close.
I have been using this kind of processes to keep track of my apps and restart them when they crash.
One minor but fundamental thing: on Symbian there is an emulator and not a simulator. The difference is that the later simulates the device on the assembly level while the former does it only on API support level. For example iPhone simulator simulates the phone on assembly level. Contrarily in Symbian the underlying API implementation might be and is completely different for the ARM and for the WINS architecture. Especially in such cases when you interact with the OS like exiting the application.
The application quit operation on Symbian is eventually implemented by throwing a special exception (I don't remember it's name, something like KExitException) that is caught by the main Active Scheduler loop that tells the kernel to shut down the process. In other words it means that it is a synchronous call. If you first call quit then startProcess then the later will be never executed. It is not that clear why does not it work if you first call startProcess and then quit: this might be an asynchronous call that can not complete before you exit, or you simple can not start the same (GUI) application in two instances. Anyway check the return value of startProcess to see whether it succeeded or not.
Your ultimate solution will be to create a watchdog process as #Riho suggested. You start the watchdog process before you call quit, in the watchdog main function you wait some seconds and restart your application. You will need SwEvent capability for your watchdog.
I have tried it with Qprocess() and it seems to be working fine (still testing for memory and thread issues)
in main.cpp I write this code (which I got from other link )
int main(int argc, char *argv[])
{
#define RESTART_CODE 1000
int return_from_event_loop_code;
QPointer<QApplication> app;
QPointer<MainWindow> main_window;
do
{
if(main_window) delete main_window;
if(app) delete app;
app = new QApplication(argc, argv);
main_window = new MainWindow;
QList<QString> lang = AppStatus::getCurrentLanguage();
QTranslator translator;
translator.load(lang.at(0));
app->installTranslator(&translator);
main_window->setOrientation(MainWindow::ScreenOrientationLockPortrait);
#if defined(Q_OS_SYMBIAN)
main_window->showMaximized();
#else
main_window->show();
#endif
return_from_event_loop_code = app->exec();
}
while(return_from_event_loop_code==RESTART_CODE);
return return_from_event_loop_code;
}
and in my method from where I have to restart my app I have written this.
QProcess::startDetached(qApp->applicationFilePath(),qApp->arguments());
qApp->exit(RESTART_CODE);
And my app is restarting like I wanted.. If any changes nedded plese let me know.