Qt - Close QThreads that are blocked by system-level calls - multithreading

I have a thread which blocks until data is received from a system resources such as a USB device. I chose this model because the amount of data may vary, and data may be received at any time. Upon exiting the application, I get the message “QThread: Destroyed while thread is still running”. How should I go about closing these threads?
I’ve looked at other problems/solutions such as:
http://www.qtcentre.org/threads/14429-Loop-inside-Qthread-causes-quot-QThread-Destroyed-while-thread-is-still-running-quot
http://www.qtcentre.org/threads/6211-QThread-Destroyed-while-thread-is-still-running
The first solution involves using a flag (included in my code) however my thread will never reach the flag check.
The second solution uses QWaitCondition but seem to be along the same lines as the first.
I’ve included a stripped down version of the code below. The system calls WaitForSingleObject() is a substitute for what I actually use (GetOverlappedResult()).
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <QObject>
#include <QThread>
#include <QReadWriteLock>
#include <QDebug>
#ifdef Q_OS_WIN
#include <windows.h>
#endif // Q_OS_WIN
#ifdef Q_OS_LINUX
#include <unistd.h>
#endif // Q_OS_LINUX
////////////////////////////////////////////////
//
// Worker Object
//
////////////////////////////////////////////////
class Worker : public QObject {
Q_OBJECT
public:
QReadWriteLock lock;
bool running;
public slots:
void loop() {
qDebug() << "entering the loop";
bool _running;
forever {
lock.lockForRead();
_running = running;
lock.unlock();
if (!_running) return;
qDebug() << "loop iteration";
#ifdef Q_OS_WIN
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
WaitForSingleObject(event, INFINITE);
#endif // Q_OS_WIN
#ifdef Q_OS_LINUX
read(0, 0, 1);
#endif // Q_OS_LINUX
}
}
};
////////////////////////////////////////////////
//
// Controller
//
////////////////////////////////////////////////
class Controller {
public:
Controller() {
myWorker.connect(&myThread, SIGNAL(started()), &myWorker, SLOT(loop()));
myWorker.moveToThread(&myThread);
myThread.start();
}
~Controller() {
// Safely close threads
myWorker.lock.lockForWrite();
myWorker.running = false;
myWorker.lock.unlock();
myThread.quit();
//myThread.wait();
//myThread.exit();
//myThread.terminate();
}
private:
QThread myThread;
Worker myWorker;
};
#endif // CONTROLLER_H

For Linux:
Sending a signal to the thread with pthread_kill() interrupted read() with failure code EINTR. sigaction() was used to register the signal, and the signal thrown was SIGUSR1.
// Global scope
void nothing(int signum) {}
...
// Within the start of the thread
pthread_t myThreadID = pthread_self(); // Get the thread ID
struct sigaction action;
action.sa_flags = 0;
sigemptyset(&action.sa_mask);
action.sa_handler = nothing;
sigaction(SIGUSR1, &action, NULL);
...
// When it's time to close the thread
pthread_kill(myThreadID, SIGUSR1);
For Windows:
Signaling the OVERLAPPED's hEvent with SetEvent() was used to unblock GetOverlappedResult().
// Store a reference to the event
HANDLE myEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
...
// Within the start of the thread
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
overlapped.hEvent = myEvent;
...
// When it's time to close the thread
SetEvent(myEvent);

Related

Pause thread execution without using condition variable or other various synchronization pritmives

Problem
I wish to be able to pause the execution of a thread from a different thread. Note the thread paused should not have to cooperate. The pausing of the target thread does not have to occur as soon as the pauser thread wants to pause. Delaying the pausing is allowed.
I cannot seem to find any information on this, as all searches yielded me results that use condition variables...
Ideas
use the scheduler and kernel syscalls to stop the thread from being scheduled again
use debugger syscalls to stop the target thread
OS-agnostic is preferable, but not a requirement. This likely will be very OS-dependent, as messing with scheduling and threads is a pretty low-level operation.
On a Unix-like OS, there's pthread_kill() which delivers a signal to a specified thread. You can arrange for that signal to have a handler which waits until told in some manner to resume.
Here's a simple example, where the "pause" just sleeps for a fixed time before resuming. Try on godbolt.
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
void safe_print(const char *s) {
int saved_errno = errno;
if (write(1, s, strlen(s)) < 0) {
exit(1);
}
errno = saved_errno;
}
void sleep_msec(int msec) {
struct timespec t = {
.tv_sec = msec / 1000,
.tv_nsec = (msec % 1000) * 1000 * 1000
};
nanosleep(&t, NULL);
}
void *work(void *unused) {
(void) unused;
for (;;) {
safe_print("I am running!\n");
sleep_msec(100);
}
return NULL;
}
void handler(int sig) {
(void) sig;
safe_print("I am stopped.\n");
sleep_msec(500);
}
int main(void) {
pthread_t thr;
pthread_create(&thr, NULL, work, NULL);
sigset_t empty;
sigemptyset(&empty);
struct sigaction sa = {
.sa_handler = handler,
.sa_flags = 0,
};
sigemptyset(&sa.sa_mask);
sigaction(SIGUSR1, &sa, NULL);
for (int i = 0; i < 5; i++) {
sleep_msec(1000);
pthread_kill(thr, SIGUSR1);
}
pthread_cancel(thr);
pthread_join(thr, NULL);
return 0;
}

Timed waiting and infinite waiting on the same condition variable?

Scenario:
I have a condition_variable based wait and signal mechanism. This works! But I need a little more than just the classic wait and signal mechanism. I need to be able to do a timed wait as well as an infinite wait "on the same condition_variable". Hence, I created a wrapper class around a condition_variable which takes care of the spurious wake up issue as well. Following is the code for that:
Code:
// CondVarWrapper.hpp
#pragma once
#include <mutex>
#include <chrono>
#include <condition_variable>
class CondVarWrapper {
public:
void Signal() {
std::unique_lock<std::mutex> unique_lock(cv_mutex);
cond_var_signalled = true;
timed_out = false;
unique_lock.unlock();
cond_var.notify_one();
}
bool WaitFor(const std::chrono::seconds timeout) {
std::unique_lock<std::mutex> unique_lock(cv_mutex);
timed_out = true;
cond_var.wait_for(unique_lock, timeout, [this] {
return cond_var_signalled;
});
cond_var_signalled = false;
return (timed_out == false);
}
bool Wait() {
std::unique_lock<std::mutex> unique_lock(cv_mutex);
timed_out = true;
cond_var.wait(unique_lock, [this] {
return cond_var_signalled;
});
cond_var_signalled = false;
return (timed_out == false);
}
private:
bool cond_var_signalled = false;
bool timed_out = false;
std::mutex cv_mutex;
std::condition_variable cond_var;
};
// main.cpp
#include "CondVarWrapper.hpp"
#include <iostream>
#include <string>
#include <thread>
int main() {
CondVarWrapper cond_var_wrapper;
std::thread my_thread = std::thread([&cond_var_wrapper]{
std::cout << "Thread started" << std::endl;
if (cond_var_wrapper.WaitFor(std::chrono::seconds(10))) {
std::cout << "Thread stopped by signal from main" << std::endl;
} else {
std::cout << "ERROR: Thread stopping because of timeout" << std::endl;
}
});
std::this_thread::sleep_for(std::chrono::seconds(3));
// Uncomment following line to see the timeout working
cond_var_wrapper.Signal();
my_thread.join();
}
Question:
Above code is good but I think there is one problem? Would I really be able to do a wait as as well do a wait_for on the same condition_variable? What if a thread has acquired cv_mutex by calling CondVarWrapper::Wait() and this one never returned for some reason. And then another thread comes in calling CondVarWrapper::WaitFor(std::chrono::seconds(3)) expecting to return out if it does not succeed in 3 seconds. Now, this second thread would not be able to return out of WaitFor after 3 seconds isnt it? In fact it wouldn't ever return. Because the condition_variable wait is a timed wait but not the lock on cv_mutex. Am I correct or Am I wrong in understanding here?
If I am correct above then I need to replace std::mutex cv_mutex with a std::timed_mutex cv_mutex and do a timed_wait in CondVarWrapper::WaitFor and do a infinite wait on CondVarWrapper::Wait? Or are there any better/easier ways of handling it?
The mutex is released when calling std::condition::wait on the condition variable cond_var. Thus, when you call CondVarWrapper::Wait from one thread, it releases the mutex when calling std::condition::wait and it hangs in there forever, the second thread can still call CondVarWrapper::WaitFor and successfully lock the mutex cv_mutex.

Make scope of lock smaller in threadsafe queue

I have a dll which has a high priority functionality that runs in a high priority thread. This dll needs to report progress. Basically a callback system is used. The issue is that the dll has no control over the amount of time the callback takes to complete. This means the high priority functionality is dependent on the implementation of the callback which is not acceptable.
The idea is to have a class inbetween that buffers the progress notifications and calls the callback.
I'm new to C++11 and it's threading functionality and trying to discover the possibilities. I have an implementation but I have an issue(at least one that I see now). When the thread awakens after the wait the mutex is reacquired and stays acquired until the next wait. This means the lock is acquired for as long as the lengthy operation continues. Adding progress will block here. Basically a lot of code for no gain. I thought of changing the code to this but I don't know if this is the correct implementation.
Progress progress = queue.front();
queue.pop();
lock.unlock();
// Do lengthy operation with progress
lock.lock();
I think I need to wait for the condition variable, but that should not be connected to the lock. I don't see how this can be done. Pass a dummy lock and use a different lock to protect the queue? How should this problem be tackled in C++11?
header file
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <queue>
#include "Error.h"
#include "TypeDefinitions.h"
struct Progress
{
StateDescription State;
uint8 ProgressPercentage;
};
class ProgressIsolator
{
public:
ProgressIsolator();
virtual ~ProgressIsolator();
void ReportProgress(const Progress& progress);
void Finish();
private:
std::atomic<bool> shutdown;
std::condition_variable itemAvailable;
std::mutex mutex;
std::queue<Progress> queue;
std::thread worker;
void Work();
};
cpp file
#include "ProgressIsolator.h"
ProgressIsolator::ProgressIsolator() :
shutdown(false),
itemAvailable(),
worker([this]{ Work(); }),
progressCallback(progressCallback),
completedCallback(completedCallback)
{
// TODO: only continue when worker thread is ready and listening?
}
ProgressIsolator::~ProgressIsolator()
{
Finish();
worker.join();
}
void ProgressIsolator::ReportProgress(const Progress& progress)
{
std::unique_lock<std::mutex> lock(mutex);
queue.push(progress);
itemAvailable.notify_one();
}
void ProgressIsolator::Finish()
{
shutdown = true;
itemAvailable.notify_one();
}
void ProgressIsolator::Work()
{
std::unique_lock<std::mutex> lock(mutex);
while (!shutdown)
{
itemAvailable.wait(lock);
while (!queue.empty())
{
Progress progress = queue.front();
queue.pop();
// Do lengthy operation with progress
}
}
}
void ProgressIsolator::Work()
{
while (!shutdown)
{
Progress progress;
{
std::unique_lock<std::mutex> lock(mutex);
itemAvailable.wait(lock, [this] { return !queue.empty(); });
progress = queue.front();
queue.pop();
}
// Do lengthy operation with progress
}
}

linux: alarm function doesn't work sometimes?

My code is as follows,The first time ,alarm works very well and handler2() function can work. however, the alarm doesn't work after it implement "doMain()" in the "handler2()".
I mean after the second time print ""In main Pleasae input: \n"", handler2() doesn't wrok anymore.
I don't know why? My code as follows:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#define MAX_LEN_COMM 64
jmp_buf jumper;
int stop =0; //o is not stop ,otherwise is stop;
void hanlder2();
void doMain();
void handler2()
{
int len_command = 0;
char character;
char commandStr[60];
printf("******************************\n");
printf("In Alarm Pleasae input: \n");
while((character=getchar())!='\n')
{
commandStr[len_command]=character;
len_command++;
}
commandStr[len_command]='\0';
printf("In Alarm input is %s\n",commandStr);
if (strcmp(commandStr,"N")==0||strcmp(commandStr,"n")==0){
printf("In Alarm You put no, we will stop alarm \n");
stop=1;
longjmp(jumper, 2);
}
else if(strcmp(commandStr,"Y")==0||strcmp(commandStr,"y")==0){
printf("In Alarm You put yes, we will continue alarm \n");
signal(SIGALRM, handler2);
alarm(5);
doMain();
}
}
void doMain(){
while(1){
setjmp(jumper);
if(stop==0){
signal(SIGALRM, handler2);
printf("return time %d\n",alarm(5));
}
int len_command = 0;
char character;
char commandStr[60];
printf("In main Pleasae input: \n");
while((character=getchar())!='\n')
{
commandStr[len_command]=character;
len_command++;
}
commandStr[len_command]='\0';
printf("In main input is %s\n",commandStr);
if (strcmp(commandStr,"N")==0||strcmp(commandStr,"n")==0){
printf("In main You put no\n");
}
else if(strcmp(commandStr,"Y")==0||strcmp(commandStr,"y")==0){
printf("In main You put yes\n");
}
}
}
void main()
{
doMain();
}
What you are doing is very wrong.
First, the signature of the handler should be void handler(int sig).
Second, there are very few functions that are safe to use within a handler so you should try to get out of a handler as quickly as possible and definitely not doing console i/o. You are using several unsafe library functions.
Lastly a signal handler is a function. It runs and returns to where your program was interrupted by the signal. During the time a handler runs signals of the same type are not deliverd. By calling doMain() from the handler - which is crazy - the handler never ends. Because it doesn't end you won't see any more alarm signals.

Qt GUI user interaction with QMessageBox from within QThread object

I'm using QThread with MyObject->moveToThread(myThread); for communication functions that take a while. A few Signals and Slots keep the GUI posted about the progress.
Howeever, some situation may occur during the threaded communication that requires user interaction - since a QMessageBox can't be created inside a thread, I was thinking to emit a signal that would allow me to pause the thread and show the dialog. But first of all, there does not seem to be a way to pause a thread, and second, this attempt probably fails because it requires a way to pass a parameter back to the thread when resuming it.
A differenet approach might be to pass all parameters in question to the thread beforehand, but this may not alway be an option.
How is this usually done?
Edit
Thanks for the comment #1 and getting my hopes up, but please elaborate on how to create e.g. a dialog from an object within a thread and how to pause it..
The following example code with Qt 4.8.1 and MSVC++ 2010 results in:
MyClass::MyClass created
MainWindow::MainWindow thread started
MyClass::start run
ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel\qwidget.cpp, line 1299
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myclass.h"
#include <QThread>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThread *thread = new QThread();
MyClass* myObject = new MyClass();
myObject->moveToThread( thread );
connect(thread, SIGNAL( started()), myObject, SLOT(start()));
connect(myObject, SIGNAL( finished()), thread, SLOT(quit()));
connect(myObject, SIGNAL( finished()), myObject, SLOT(deleteLater()));
connect(thread, SIGNAL( finished()), thread, SLOT(deleteLater()));
thread->start();
if( thread->isRunning() )
{
qDebug() << __FUNCTION__ << "thread started";
}
}
MainWindow::~MainWindow()
{
delete ui;
}
myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0);
signals:
void finished();
public slots:
void start();
};
#endif // MYCLASS_H
myclass.cpp
#include "myclass.h"
#include <QMessageBox>
#include <QDebug>
MyClass::MyClass(QObject *parent) :
QObject(parent)
{
qDebug() << __FUNCTION__ << "created";
}
void MyClass::start()
{
qDebug() << __FUNCTION__ << "run";
// do stuff ...
// get information from user (blocking)
QMessageBox *msgBox = new QMessageBox();
msgBox->setWindowTitle( tr("WindowTitle") );
msgBox->setText( tr("Text") );
msgBox->setInformativeText( tr("InformativeText") );
msgBox->setStandardButtons( QMessageBox::Ok | QMessageBox::Cancel);
msgBox->setDefaultButton( QMessageBox::Ok);
msgBox->setEscapeButton( QMessageBox::Cancel);
msgBox->setIcon( QMessageBox::Information);
int ret = msgBox->exec();
// continue doing stuff (based on user input) ...
switch (ret)
{
case QMessageBox::Ok:
break;
case QMessageBox::Cancel:
break;
default:
break;
}
// do even more stuff
emit finished();
}
Use Qt::BlockingQueuedConnection in a signal/slot connection (the call to QObject::connect()).
http://doc.qt.digia.com/qt/qt.html#ConnectionType-enum
This will block your thread until the slot on the UI thread returns, the slot in the UI thread is then free to display a messagebox/modal dialog/whatever you want to do.
You must be sure that your worker thread is actually not on the UI thread, because as the docs say this will cause a dead lock if the signal and slot are on the same thread (since it will block itself).
I can't give any specific code right now, but I would do it like this:
In MyClass::start() lock a QMutex.
Emit a signal e.g. messageBoxRequired().
Wait on a shared QWaitCondition on the recent mutex. This will also unlock the mutex while the thread is waiting.
In a slot in your MainWindow, e.g. showMessageBox(), show the message box.
Store the returned value in a member of MyClass. You can do this by offering a setter and getter which use the mutex in order to protect the member. Obviously MyClass itself should only access that member with those setters/getters itself. (Also see QMutexLocker for that).
Call wakeOne() or wakeAll() on the shared QWaitCondition.
The previous wait() call will return and MyClass::start() will continue execution. If I understand the docs correctly, QWaitCondition will lock the mutex again before it returns from wait(). This means you have to unlock the mutex directly after the wait() call.
You can access the message box's return value from your class member (using a thread-safe getter)
Implementations for thread-safe setters/getters would be as follows:
void MyClass::setVariable( int value )
{
QMutexLocker( &_mutex );
_value = value;
}
int MyClass::getVariable() // Not sure if a 'const' modifier would work here
{
QMutexLocker( &_mutex );
return _value;
}

Resources