QThread::finished() is never emitted? - multithreading

I don't have a forever loop like this question, but it still doesn't emit the finished() signal,
In the constructor of a class:
connect (&thread, SIGNAL(started()), SLOT(threadFunc()));
connect (&thread, SIGNAL(finished()), SLOT(finished()));
In the finished() function,
void XX::finished()
{
qDebug() << "Completed";
}
void XX::threadFunc()
{
qDebug() << "Thread finished"; // only single line, finishes immediately
}
But I never see the finished() get called, everytime before I start the thread with thread.start(), I must call thread.terminate() manually, did I misunderstood the usage of QThread?

QThread will emit finished signal when QThread::run method is finished. Perhaps, you have incorrect implementation of this.
Default implementation of run method looks like this. It just calls another exec method.
void QThread::run()
{
(void) exec();
}
Implementation of exec method is a bit more complex. Now I simplified it.
int QThread::exec()
{
// .....
if (d->exited) {
return d->returnCode;
}
// ......
QEventLoop eventLoop;
int returnCode = eventLoop.exec();
return returnCode;
}
Judging by code, it can finish in two cases. In first case if it is already exited. In second it enters the event loop and waits until exit() is called.
How we can see now, your infinity thread loop is here. So you need QThread::quit() which is equal QThread::exit(0).
P.S. Don't use terminate. It is dangerous.

Related

c++: How to quit a multi-threading program properly

In my c++11 project, I need to generate two threads which run infinitely. Here is an example:
static vector<int> vec;
static std::mutex mtx;
static std::condition_variable cond;
static bool done = false;
void f1()
{
while(!done)
{
// do something with vec and mtx
}
}
void f2()
{
while(!done)
{
// do something with vec and mtx
}
}
thread t1(f1);
thread t2(f2);
void finish(int s)
{
done = true;
// what should I do???
}
int main()
{
signal(SIGINT, finish);
t1.join();
t2.join();
return 0;
}
Normally, I won't stop or kill this program. But in case of exception, I think I need to do something for ctrl-c, which is used to kill the program. But I don't know how to quit this program properly.
If I'm right, t1 and t2 might continue executing even if the main has returned 0. So I think I need to make them detach like this:
void finish()
{
done = true;
t1.detach();
t2.detach();
}
However, when I execute the program and do ctrl-c, I get an error:
terminate called after throwing an instance of 'std::system_error'
I've found this link, so I think the problem is the same: mtx and/or cond has been destroyed while t1 or t2 hasn't finished yet.
So how could I kill the program properly? Or I don't need to deal with the signal ctrl-c and the program itself knows what to do to quit properly?
done should be std::atomic<bool>, or unsequenced reads/writes are not legal.
Accessing atomic variables is only safe in a signal handler if std::atomic<bool>::is_lock_free is true. Check that. If it isn't true, your program should probably abort with an error in main.
When you .join(), you wait for the thread to finish executing. And you don't want to exit main unless the threads have finished.
In short, do this:
static std::atomic<bool> done = false;
(rest of code goes here)
int main()
{
if (!done.is_lock_free()) return 10; // error
signal(SIGINT, finish);
t1.join();
t2.join();
}

How to stop a running thread from another thread?

I want to put a Stop button to stop all threads except main thread. In order to do, this codes like belows have been written:
serialclass *obje = new serialclass();
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThread *thread = new QThread();
obje->moveToThread(thread);
connect(this,SIGNAL(signal_stop()),obje,SLOT(stop_thread()),Qt::UniqueConnection);
thread->start();
}
void MainWindow::on_pushButton_baslat_clicked() //başlat butonu
{
connect(this,SIGNAL(signal()),obje,SLOT(function1()), Qt::UniqueConnection);
emit signal();
}
void MainWindow::on_pushButton_stop_clicked()
{
qDebug()<<QThread::currentThreadId()<<"=current thread(main thread)";
emit signal_stop();
}
In SerialClass part :
void serialclass::function1()
{
int i;
for(i=0;i<99999;i++)
{
qDebug()<<i;
}
}
void serialclass::stop_thread()
{
qDebug()<<QThread::currentThreadId()<<"Serial thread";
QThread::currentThread()->exit();
}
Now, When i push start button everthing works good.But, when i push start button and i push stop button while function1 is running, program crashs.
if i use sleep function instead of exit, Firstly function1 ends, after that sleep function starts.
What i have to do to stop child thread when they are working. I mean i dont want to wait their process. Want to Just stop
If you're busy looping in a reimplemented thread, you should use QThread::isInterruptionRequested() to break out of the loop and immediately return from the run() function:
void serialclass::function1() {
while (! thread()->isInterruptionRequested())
msleep(10);
}
If you're using a QThread as-is for its event loop, you need to call its quit() method.
To factor it out:
void stop(QThread * thread) {
thread->requestInterruption();
thread->quit();
}
What you're doing in function1() is wrong. You should never block the thread that way. You're writing your code in pseudosynchronous style. Invert the control flow to always keep control in the event loop, and QThread::quit() will then work as expected.

Keeping threads alive even if the main thead has terminated

I am not sure if my question is correct, but I have the following example, where the main thread creates two additional threads.
Since I am not using join command at the end of the main, it will continue execution and in the same time, the two created threads will work in parallel. But since the main is terminated before they finish their execution, I am getting the following output:
terminate called without an active exception
Aborted (core dumped)
Here's the code:
#include <iostream> // std::cout
#include <thread> // std::thread
#include <chrono>
void foo()
{
std::chrono::milliseconds dura( 2000 );
std::this_thread::sleep_for( dura );
std::cout << "Waited for 2Sec\n";
}
void bar(int x)
{
std::chrono::milliseconds dura( 4000 );
std::this_thread::sleep_for( dura );
std::cout << "Waited for 4Sec\n";
}
int main()
{
std::thread first (foo);
std::thread second (bar,0);
return 0;
}
So my question is how to keep these two threads working even if the main thread terminated?
I am asking this because in my main program, I have an event handler ,and for each event I create a corresponding thread. But the main problem when the handler creates a new thread, the handler will continue execution. Until it is destroyed which will cause also the newly created thread to be destroyed. So my question is how to keep the thread alive in this case?
Also if I use a join it will convert back to serialization.
void ho_commit_indication_handler(message &msg, const boost::system::error_code &ec)
{
.....
}
void event_handler(message &msg, const boost::system::error_code &ec)
{
if (ec)
{
log_(0, __FUNCTION__, " error: ", ec.message());
return;
}
switch (msg.mid())
{
case n2n_ho_commit:
{
boost::thread thrd(&ho_commit_indication_handler, boost::ref(msg), boost::ref(ec));
}
break
}
};
Thanks a lot.
Keeping the threads alive is a bad idea, because it causes a call to std::terminate. You should definitively join the threads:
int main()
{
std::thread first (foo);
std::thread second (bar, 0);
first.join();
second.join();
}
An alternative is to detach the threads. However you still need to assert that the main thread lives longer (by e.g. using a mutex / condition_variable).
This excerpt from the C++11 standard is relevant here:
15.5.1 The std::terminate() function [except.terminate]
1 In some situations exception handling must be abandoned for less subtle error
handling techniques. [ Note: These situations are:
[...]
-- when the destructor or the copy assignment operator is invoked on an
object of type std::thread that refers to a joinable thread
Hence, you have to call either join or detach on threads before scope exit.
Concerning your edit: You have to store the threads in a list (or similar) and wait for every one of them before main is done. A better idea would be to use a thread pool (because this limits the total number of threads created).

QThread state when at start() call thread is still running, but after is already not

I have a GUI thread where I call write(QString text) method of another MyQThread.
MyQthread contains QMutex mutex and QList<QString> list. Here is the write() and run() methods of MyQThread:
void MyQThread::write(QString text)
{
mutex.lock();
list.append(text); //Point C
mutex.unlock();
start(); //Point D
}
void MyQThread::run()
{
mutex.lock();
while(!list.isEmpty())
{
QString text = list.takeFirst();
mutex.unlock();
...//do something
mutex.lock(); //Point A
}
mutex.unlock(); //Point B
}
For example we are at the 'point A'. After this point we are checking the list and it is empty, so we are going to 'point B'. At this moment write() is called, mutex is still locked, so GUI thread is waiting before 'point C'.
Now we are at the 'point B', after this GUI thread is unlocked and start() ('Point D') is called.
Is it possible, that at 'point D' MyQThread is still running?
In this case calling of start() do nothing. And newly added item in the list will not be processed in run() until next call of the write().
Additional information. In my case here is only one instance of MyQThread.
Yes. Although the probability of having a race condition is low, I believe there's still a chance that QThread will still be sending signals and such. Use QThread::wait before you call start() to be sure.
Edit: Agreed on the need to consider QMutexLocker. That code's going to get scary complicated pretty fast and you can't be sure that you'll remember to unlock with every exit point.
Edit2: Perhaps a QReadWriteLock might be more interesting in your case?
#alexisdm thanks for the idea. What about this solution:
class MyQThread:
public: QThread
{
...
QList<QString> list;
QMutex mutex;
QWaitCondition listNotEmpty;
}
void MyQThread::write(QString text)
{
QMutexLocker locker(&mutex);
list.append(text);
listNotEmpty.wakeAll();
}
void MyQThread::run()
{
forever
{
mutex.lock();
if(list.isEmpty())
listNotEmpty.wait(&mutex);
if(list.isEmpty())
{
mutex.unlock();
continue;
}
QString text = list.takeFirst();
mutex.unlock();
...//do something
}
}
And what about the second parameter of wait() - unsigned long time = ULONG_MAX.
It seems that in my case it will not be error, when write() method is not called for a long time and wait() will return false in run() after ULONG_MAX. And in this case I need just to wait again...
And in documentation is written:
The mutex will be returned to the same locked state.
Does it mean, that mutex will be always locked after wait() even if mutex was not locked before wait() or wait() returns false?
QThread has the methods 'isRunning' and 'isFinished'. So you could query the thread state. And sure, your thread could still be running at 'Point D'.
But you really should stop here and do some reading.
https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
and
http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html
And most certainly the Qt docs about the QMutexLocker.

Can't get my thread to execute with SetEvent and WaitForSingleObject

I'm trying to create a thread and let it run until my main signals it to start, which I think is done with SetEvent. But the code in the thread is never executed. Below is the bare code I have stripped down of (I think) unrelated functions. Is the algorithm correct ?
Here is what I thought it did :
When in the main, the thread is created, which means it'll run in the background. When the event is set (SetEvent), the thread picks it up at WaitForSingleObject and then execute the code in the thread, right ?
HANDLE hThread;
HANDLE Event;
DWORD Thread()
{
while(1)
{
wait = WaitForSingleObject(Event, INFINITE)
//This is where I want to execute something
}
}
int _tmain()
{
DWORD dw;
int i;
Event = CreateEvent(NULL,false,false,NULL);
hThread = CreateThread(NULL,0,Thread,EventA,0,NULL);
while(1)
{
if (condition is correct)
{
SetEvent(Event);
}
CloseHandle(Thread);
CloseHandle(Event);
}
return 0;
}
Thanks for having read.
Move CloseHandle lines out of the while loop.

Resources