I have a Qt application that connects to a card reader using various pcsc implementations under GNU/Linux, MacOS, and Windows. All communication with the card runs in a worker thread.
In one scenario, the user starts an operation requiring communication with the card via a card reader. The card reader has a keyboard and during the authentication procedure the user must enter their PIN on the reader's keyboard.
This operation is implemented by a call to SCardControl() (see e.g. the Microsoft documentation). As long as the user is working with the reader, the call to SCardControl() does not terminate and the worker thread is blocked by it.
At this point, the user might decide to close the application while the operation is still pending. Closing the application at this point causes the application to crash (on Linux with signal SIGABRT) because:
The worker thread is blocked waiting for SCardControl() to return.
The main thread cannot stop the blocked thread: neither quit() nor terminate() cause the thread to finish.
When the application is exited, the QThread object for the worker thread is destroyed and, since the thread is still running state, it throws a signal to indicate an error.
I have tried several solutions.
Subclass QThread and create a worker thread which calls setTerminationEnabled(true); to allow termination through QThread::terminate(). This does not work on MacOS: when QThread is destroyed, the thread is still in a running state and the signal SIGABRT is emitted.
Handle signal SIGABRT on shutdown and ignore it. This did not seem to be a good idea but I wanted to try it out before discarding it. After ignoring signal SIGABRT, a signal SIGSEGV is received and the application crashes. I had adapted the approach described here.
Try to unblock the thread by sending a command to the card reader from the main thread. I tried SCardCancel(), SCardDisconnect() and SCardReleaseContext() but none of these commands has any effect on the blocked thread.
I find it quite strange that it is not possible to cleanly shutdown an application when a thread is blocked on some function call, but all the solutions I have tried have not worked and I have run out of ideas. Did I overlook something? Does anybody have any useful hint?
EDIT
I looked into the Qt source code for QThread and found out that on Unix-like platforms QThread::terminate() uses pthread_cancel() internally. But apparently pthread_cancel() does not work / does nothing on Darwin, see e.g. here and here.
So, maybe I will really have to go with the option of showing a dialog to the user asking to remove the card from the reader.
Cleanly shutting down a thread is not possible from outside if it is blocked in a call. You can, however, prevent user from quitting the application before the operation has completed.
void MainWindow::closeEvent(QCloseEvent *closeEvent) {
if (workerBlocked) closeEvent->ignore();
}
In addition, you can show a dialog telling the user the operation has to be completed first.
Also, if possible, you can let the window close but keep the application alive until the operation is complete by setting qApp->setQuitOnLastWindowClosed(false);
The problem boils down to the fact that a QThread object isn't destructible while the associated thread is running. Usually, it would a print statement like this to the debug output:
QThread: Destroyed while thread is still running
Don't agonize over trying to get SCardControl to return so that the worker thread can be quit safely (since it doesn't return as long as the user is interacting with the reader). Instead, You can follow this answer to destruct the QThread object in a safe manner with a minimum amount of changes to your current implementation.
Here is an example that shows what I mean:
#include <QtWidgets>
//a thread that can be destroyed at any time
//see http://stackoverflow.com/a/25230470
class SafeThread : public QThread{
using QThread::run;
public:
explicit SafeThread(QObject* parent= nullptr):QThread(parent){}
~SafeThread(){ quit(); wait(); }
};
//worker QObject class
class Worker : public QObject {
Q_OBJECT
public:
explicit Worker(QObject* parent = nullptr):QObject(parent){}
~Worker(){}
Q_SLOT void doBlockingWork() {
emit started();
//the sleep call blocks the worker thread for 10 seconds!
//consider it a mock call to the SCardControl function
QThread::sleep(10);
emit finished();
}
Q_SIGNAL void started();
Q_SIGNAL void finished();
};
int main(int argc, char* argv[]) {
QApplication a(argc, argv);
//setup worker thread and QObject
Worker worker;
SafeThread thread;
worker.moveToThread(&thread);
thread.start();
//setup GUI components
QWidget w;
QVBoxLayout layout(&w);
QPushButton button("start working");
QLabel status("idle");
layout.addWidget(&button);
layout.addWidget(&status);
//connect signals/slots
QObject::connect(&worker, &Worker::started, &status,
[&status]{ status.setText("working. . .");} );
QObject::connect(&worker, &Worker::finished, &status,
[&status]{ status.setText("idle");} );
QObject::connect(&button, &QPushButton::clicked, &worker, &Worker::doBlockingWork);
w.show();
return a.exec();
}
#include "main.moc"
Notice that the SafeThread's destructor makes sure to wait() until the associated thread has finished execution. And only afterwards, the main thread can proceed to call QThread's destructor.
Related
I created a thread with class A and after deleted class A, the thread is not deleted. It continues running.
I explicitly called the thread destructor, quit and exit function but still, the thread did not stop running.
Is there any thing like KILL function to stop the thread execution
void A::init()
{
WorkerThread *Thread = new WorkerThread(this);
}
void B::slotClose()
{
A *obj = getObj();
if(obj)
{
m_pScene->removeItem(obj);
obj->deleteLater(); // this calls thread distructor also but thread execution is not stopping
}
}
From the docs:
Note that deleting a QThread object will not stop the execution of the thread it manages. Deleting a running QThread (i.e. isFinished() returns false) will result in a program crash. Wait for the finished() signal before deleting the QThread.
You should never delete a running QThread object.
So I think it would be the best for you to write some termination/quitting logic in your WorkerThread, expose some slot for example quit and connect signal with this quit slot.
If you just want to terminate the thread no matter what, just connect destroyed SIGNAL to terminate SLOT (http://doc.qt.io/qt-5/qthread.html#terminate)
So assuming your A class derives from QObject, what would you do inside this class is:
connect(this, SIGNAL(destroyed()), Thread, terminate());
If you have your own slot quit exposed, so you make sure you properly stop all that's executing in your loop just instead terminate() use quit().
connect(this, SIGNAL(destroyed()), Thread, quit());
Here's an example of implementing such a logic: http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
Or just put quit = true in your ThreadWorker destructor.
It should be straightforward. Good luck!
Also some official documentation with examples (imo doing it right):
https://wiki.qt.io/QThreads_general_usage
https://doc.qt.io/archives/qt-5.8/qtnetwork-blockingfortuneclient-example.html
https://doc.qt.io/archives/qt-5.8/qtcore-threads-mandelbrot-example.html
Here is how Qt signal/slot connection works:
Direct Connection The slot is invoked immediately, when the signal is emitted. The slot is executed in the emitter's thread, which is not necessarily the receiver's thread.
Queued Connection The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.
Blocking Queued Connection The slot is invoked as for the Queued Connection, except the current thread blocks until the slot returns.
Note: Using this type to connect objects in the same thread will cause deadlock.
And there's an extra one which is actually the default: Auto Connection If the signal is emitted in the thread which the receiving object has affinity then the behavior is the same as the Direct Connection. Otherwise, the behavior is the same as the Queued Connection."
The default works pretty well as expected in most cases:
If within a worker thread, queued execution through a queued connection
If within the object thread, execution is made right away
However, when a signal is emited from a thread, you have two options to handle it: "Queued" or "Blocking Queued" Connection.
Why is there no mode that would behave like that:
If within a worker thread, blocking queued execution
If within the object thread, execution is made right away
Because, as the documentation mentions, using a Blocking Queued Connection in the same thread will cause deadlock....so it's a real pain to handle, I often had to create and manage two signals and connections in my code to handle that:
class A
{
Q_OBJECT
public:
A()
{
connect( this, SIGNAL(changedFromThread()), this, SLOT(update()), Qt::BlockingQueuedConnection );
connect( this, SIGNAL(changedNotFromThread()), this, SLOT(update()) );
}
void notifySomethingChanged()
{
if ( QObject().thread() != thread() )
emit changedFromThread(); // would dead-lock if in same thread
else
emit changedNotFromThread();
}
public slots:
void update()
{
// Do some changes to A that cannot be done from a worker thread
}
signals:
void changedFromThread();
void changedNotFromThread();
};
If such a mode (let's call it Qt::AutoBlockingConnection was available), I could have written:
class A
{
Q_OBJECT
public:
A()
{
connect( this, SIGNAL(changedFromThread()), this, SLOT(update()), Qt::AutoBlockingConnection );
}
void notifySomethingChanged()
{
emit changedFromThread(); // would dead-lock if in same thread
}
public slots:
void update()
{
// Do some changes to A that cannot be done from a worker thread
}
signals:
void changedFromThread();
};
Is there any good reason why a thread-friendly connection was only provided to swap between Qt::DirectConnection and Qt::QueuedConnection but none to swap between Qt::DirectConnection and Qt::BlockingQueuedConnection?
I would guess that the Qt dev team do not want you to specify the connection type at all.
I can understand this design, in a sense that intentional blocking should almost always be avoided, even more so if you are blocking the UI Thread.
If you wish to synchronize 2 QObject living in different threads, use signals and slots in both of them, and connect them accordingly.
However, if you are in a Master-Slave scenario (typically QMainWindow owning a QObject with QObject::moveToThread(new QThread)), you can :
Listen to signals from the QObject into your QMainWindow
Call QObject slots using QMetaObject::invokeMethod into
QMainWindow, so the method calls are processed asynchronously by
the QObject thread.
I have a condition where I have unknown amount of 3rd party threads calling a callback in my application. That callback emits a signal in the context of the threads that called it. Always the same signal, but 10 different threads can emit it at any given moment.
I'd like to queue all of those singlas and process them with the appropriate slot in the context of a single QThread I own.
How do I do that? The following code does not work. Although I see it signals being emitted, from different threads, my "On..." is never called.
QObject::connect(this,SIGNAL(ProcessQueuedOutEvent(int)),
this,
SLOT(OnProcessQueuedOutEvent(int)),
Qt::QueuedConnection);
Does your QThread run the event loop? It has to do it to receive signals:
Queued Connection The slot is invoked when control returns to the
event loop of the receiver's thread. The slot is executed in the
receiver's thread.
Basically queued connection works the following way:
The originator issues a signal.
Qt creates an event and posts it into the receiver event queue.
The receiver goes through its event queue, picks up the events and dispatches the signals into the connected slots.
Hence if you do not run the event queue, the signals are posted but your thread will never receive them.
So basically your thread should do some initialization in run() but then call exec() and pass it to Qt.
If your thread also needs to run some periodic operations besides checking for signals, you can do that by using QTimer::singleShot timers posting signals to the same thread.
See http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads
PS. If you pass the pointers via queued connections, the pointer must be valid until the signal is processed, which may be after your function which posted the signal existed. A common error is to post signals with strings as a parameters which are stored in a local char[] buffer. At the moment the buffer is accessed the original function is finished, and the string is already gone. Those errors depend on thread scheduling and therefore hard to debug. If you pass the pointers via queued connection, they must be heap-allocated and the callee must be responsible to free them.
If I understand your problem correctly, you have a callback function executed by many threads. This callback function should emit a signal connected to a slot in a object which is in another thread.
What I suggest is to create a threaded receiver object, using the pattern (moveToThread). Then using the postEvent method to a private implementation method. The call is thread safe (the parameter is copied).
So your callbacks can directly and safely call:
OnProcessQueuedOutEvent
which posts an event to the QThread event loop.
Receiver.h
class Receiver : public QObject
{
Q_OBJECT
public:
explicit Receiver( QObject* parent = 0 );
virtual ~Receiver();
public slots:
void OnProcessQueuedOutEvent( int val );
private slots:
void OnProcessQueuedOutEventImpl( int val );
private:
QThread m_thread;
};
Receiver.cpp
Receiver::Receiver( QObject* parent )
: QObject(parent)
{
moveToThread(&m_thread);
m_thread.start();
}
Receiver::~Receiver()
{
// Gracefull thread termination (queued in exec loop)
if( m_thread.isRunning() ) {
m_thread.quit();
m_thread.wait();
}
}
void OnProcessQueuedOutEvent( int val )
{
QMetaObject::invokeMethod(this, "OnProcessQueuedOutEventImpl", Q_ARG(int,val));
}
void OnProcessQueuedOutEventImpl( int val )
{
// do stuff here
}
I want to make a function that stops the main thread and restarts restarts it after a couple of seconds. I tried the following:
void Mainwindow::timeout()
{
QTimer timer;
timer.setSingleShot(true);
timer.setInterval(time*1000);
connect(&timer,SIGNAL(timeout()),MainWindow::thread(),SLOT(start()));
timer.start();
SuspendThread(MainWindow::thread());
}
Unfortunately this doesnt do a whole lot... Any tips?
Maybe I am overlooking something, but a "function that stops [...] and restarts after a couple of seconds" sounds like sleep() to me. Let the OS do the timing instead of re-inventing the wheel.
Or is there any reason you can't post some message to the main thread? In this simple use case maybe even via a single mutex would be enough. Set the mutex from another thread, check it in the main threads event loop and possibly call sleep() directly.
That also eases debugging, as you have a single place the main thread will go sleeping willingly instead of being suspendend on the fly by other threads.
your timer object is destroyed at the end of the the Mainwindow::timeout() function, so it will never emit its timeout() signal.
I am not sure why you would want to stop event loop, but you can sleep your thread by waiting on locked mutex for x milliseconds.
In the code below you will use waitCondition.wait(&mutex, msecs); to wait on a condition variable for maximum msecs milliseconds. Since mutex is locked, as there is no another thread which will send wake up signal, this will block your thread for timeout milliseconds. Reference is here.
#include <QWaitCondition>
#include <QMutex>
class Sleep
{
public:
static void msleep(unsigned long msecs)
{
QMutex mutex;
mutex.lock();
QWaitCondition waitCondition;
waitCondition.wait(&mutex, msecs);
mutex.unlock(); // Not necessary since new mutex will always be created,
// but since destroying locked mutex
// is bringing undefined behavior, let's follow some ethics
}
};
I'm writing a multithread plugin based application. I will not be the plugins author. So I would wish to avoid that the main application crashes cause of a segmentation fault in a plugin. Is it possible? Or the crash in the plugin definitely compromise also the main application status?
I wrote a sketch program using qt cause my "real" application is strongly based on qt library. Like you can see I forced the thread to crash calling the trimmed function on a not-allocated QString. The signal handler is correctly called but after the thread is forced to quit also the main application crashes. Did I do something wrong? or like I said before what I'm trying to do is not achievable?
Please note that in this simplified version of the program I avoided to use plugins but only thread. Introducing plugins will add a new critical level, I suppose. I want to go on step by step. And, overall, I want to understand if my target is feasible. Thanks a lot for any kind of help or suggestions everyone will try to give me.
#include <QString>
#include <QThread>
#include<csignal>
#include <QtGlobal>
#include <QtCore/QCoreApplication>
class MyThread : public QThread
{
public:
static void sigHand(int sig)
{
qDebug("Thread crashed");
QThread* th = QThread::currentThread();
th->exit(1);
}
MyThread(QObject * parent = 0)
:QThread(parent)
{
signal(SIGSEGV,sigHand);
}
~MyThread()
{
signal(SIGSEGV,SIG_DFL);
qDebug("Deleted thread, restored default signal handler");
}
void run()
{
QString* s;
s->trimmed();
qDebug("Should not reach this point");
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyThread th(&a);
th.run();
while (th.isRunning());
qDebug("Thread died but main application still on");
return a.exec();
}
I'm currently working on the same issue and found this question via google.
There are several reasons your source is not working:
There is no new thread. The thread is only created, if you call QThread::start. Instead you call MyThread::run, which executes the run method in the main thread.
You call QThread::exit to stop the thread, which is not supposed to directly stop a thread, but sends a (qt) signal to the thread event loop, requesting it to stop. Since there is neither a thread nor an event loop, the function has no effect. Even if you had called QThread::start, it would not work, since writing a run method does not create a qt event loop. To be able to use exit with any QThread, you would need to call QThread::exec first.
However, QThread::exit is the wrong method anyways. To prevent the SIGSEGV, the thread must be called immediately, not after receiving the (qt) signal in its event loop. So although generally frowned upon, in this case QThread::terminate has to be called
But it is generally said to be unsafe to call complex functions like QThread::currentThread, QThread::exit or QThread::terminate from signal handlers, so you should never call them there
Since the thread is still running after the signal handler (and I'm not sure even QThread::terminate would kill it fast enough), the signal handler exits to where it was called from, so it reexecutes the instruction causing the SIGSEGV, and the next SIGSEGV occurs.
Therefore I have used a different approach, the signal handler changes the register containing the instruction address to another function, which will then be run, after the signal handler exits, instead the crashing instruction. Like:
void signalHandler(int type, siginfo_t * si, void* ccontext){
(static_cast<ucontext_t*>(ccontext))->Eip = &recoverFromCrash;
}
struct sigaction sa;
memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = &signalHandler;
sigaction(SIGSEGV, &sa, 0);
The recoverFromCrash function is then normally called in the thread causing the SIGSEGV. Since the signal handler is called for all SIGSEGV, from all threads, the function has to check which thread it is running in.
However, I did not consider it safe to simply kill the thread, since there might be other stuff, depending on a running thread. So instead of killing it, I let it run in an endless loop (calling sleep to avoid wasting CPU time). Then, when the program is closed, it sets a global variabel, and the thread is terminated. (notice that the recover function must never return, since otherwise the execution will return to the function which caused the SIGSEGV)
Called from the mainthread on the other hand, it starts a new event loop, to let the program running.
if (QThread::currentThread() != QCoreApplication::instance()->thread()) {
//sub thread
QThread* t = QThread::currentThread();
while (programIsRunning) ThreadBreaker::sleep(1);
ThreadBreaker::forceTerminate();
} else {
//main thread
while (programIsRunning) {
QApplication::processEvents(QEventLoop::AllEvents);
ThreadBreaker::msleep(1);
}
exit(0);
}
ThreadBreaker is a trivial wrapper class around QThread, since msleep, sleep and setTerminationEnabled (which has to be called before terminate) of QThread are protected and could not be called from the recover function.
But this is only the basic picture. There are a lot of other things to worry about: Catching SIGFPE, Catching stack overflows (check the address of the SIGSEGV, run the signal handler in an alternate stack), have a bunch of defines for platform independence (64 bit, arm, mac), show debug messages (try to get a stack trace, wonder why calling gdb for it crashes the X server, wonder why calling glibc backtrace for it crashes the program)...