C++ application does not kill all processes on exit - c++

This is my main.cpp which starts the mainwindow:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TabWindow w;
w.show();
return a.exec();
}
Even with the a.connect(...) I do not understand why myApplication.exe still runs after I close the mainwindow. Any suggestions on how I can fully end all processes after the quit button is clicked?
EDIT: The Qt Documentation says this:
We recommend that you connect clean-up code to the aboutToQuit() signal, instead of putting it in your application's main() function. This is because, on some platforms, the QApplication::exec() call may not return.

There's nothing wrong with your code. And your connect doesn't do anything.
Unless you call QGuiApplication::setQuitOnLastWindowClosed(true) somewhere, application should exit when the last window is closed. Probably you block event loop somewhere in your window code.

Thanks to the comment posted by #ratchetfreak in my question, I figured out where the problem was.
In my MainWindow, I started a worker thread which was not terminated and thus still persisted as a process after the application was closed. In order to fix this, I registered the close event and kept track of the existence of the thread - i.e. basically, ignored the closeEvent until the thread was deleted as well.
void MainWindow::closeEvent(QCloseEvent *event)
{
if (workerThreadExists) {
// Gracefully exiting all tasks inside the worker thread
while (workerThreadExists){
event->ignore();
}
event->accept();
}
}
...and for me workerThreadExists is just a BOOLEAN that is set to true once the thread is created and then it is set to false when the thread is deleted. Hope this helps!

You should have something like this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TabWindow w;
w.show();
return a.exec();
}
// Do quit in your TabWindow:
TabWindow::TabWindow()
: public QWidget(NULL)
{
connect( ui->myQuitButton, SIGNAL( clicked() ), qApp, SLOT( quit() ) );
}

just replace
return a.exec();
with
return 0;
That should end all processes which is associated with that program.

Related

Qt - Close app if QInputDialog canceled [duplicate]

Why does this program run normally and display the main window? I would expect it to exit since quit() is called in the constructor.
Main.cpp:
#include<QApplication>
#include"MainWindow.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
qApp->quit();
}
void MainWindow::closeEvent(QCloseEvent *)
{
qDebug("Hello world!");
}
Since QCoreApplication::quit() is a no-op until the event loop has been started, you need to defer the call until it starts. Thus, queue a deferred method call to quit().
The following lines are functionally identical, either one will work:
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
//or
QTimer::singleShot(0, qApp, SLOT(quit()));
// or - see https://stackoverflow.com/a/21653558/1329652
postToThread([]{ QCoreApplication::quit(); });
// or
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
Calling QCoreApplication::quit() is the same as calling QCoreApplication::exit(0).
If you look at the docs of the latter function:
After this function has been called, the application leaves the main
event loop and returns from the call to exec(). The exec() function
returns returnCode. If the event loop is not running, this function
does nothing.
In you example, the event loop has not been started yet when MainWindows constructor is called, hence the call to quit() does nothing.

Application not quit when sending QApplication::exit or QApplication::quit [duplicate]

Why does this program run normally and display the main window? I would expect it to exit since quit() is called in the constructor.
Main.cpp:
#include<QApplication>
#include"MainWindow.h"
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
MainWindow mainWindow;
mainWindow.show();
return app.exec();
}
MainWindow.cpp:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
qApp->quit();
}
void MainWindow::closeEvent(QCloseEvent *)
{
qDebug("Hello world!");
}
Since QCoreApplication::quit() is a no-op until the event loop has been started, you need to defer the call until it starts. Thus, queue a deferred method call to quit().
The following lines are functionally identical, either one will work:
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
//or
QTimer::singleShot(0, qApp, SLOT(quit()));
// or - see https://stackoverflow.com/a/21653558/1329652
postToThread([]{ QCoreApplication::quit(); });
// or
QMetaObject::invokeMethod(qApp, "quit", Qt::QueuedConnection);
Calling QCoreApplication::quit() is the same as calling QCoreApplication::exit(0).
If you look at the docs of the latter function:
After this function has been called, the application leaves the main
event loop and returns from the call to exec(). The exec() function
returns returnCode. If the event loop is not running, this function
does nothing.
In you example, the event loop has not been started yet when MainWindows constructor is called, hence the call to quit() does nothing.

Qt5 App crashes on close (QWidget::show)

So I have been stuck at this problem for a while now. For some reason, my application always crashes on close and this is the error message I get:
The inferior stopped because it triggered an exception.
Stopped in thread 0 by: Exception at 0x50c15a08, code: 0xc0000005: read access violation at: 0x0, flags=0x0 (first chance)
The stack shows the following:
QWidget::show Line: 7030
And this is what my main.cpp currently looks like:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
I have no clue why the crash is occurring.
A little background: This is a multi-threaded application (using both QThread and QtConcurrent). When the threads are NOT started, the application closes just fine. Hence I added the following check to ensure that the thread is being terminated properly but this is not helping:
void MainWindow::closeEvent(QCloseEvent *event)
{
if (thread->isRunning()) {
thread->terminate();
while(!thread->isFinished()){
}
event->accept();
}
}
EDIT: How the new thread was created
QThread *myThread = new QThread(this);
Worker *worker = new Worker(this, user, p);
worker->moveToThread(myThread);
connect(myThread, SIGNAL(started()), worker, SLOT(doWork()));
connect(worker, SIGNAL(workDone()), this, SLOT(deleteThread()));
myThread->start();
...and this is how I am handling the deletion of the thread after the download completes:
void MainWindow::deleteThread(){
worker->deleteLater();
myThread->quit();
while(!myThread->isFinished()){
}
myThread->deleteLater();
}
You should either listen for terminated signal from the thread or wait for the thread to terminate. Telling the thread to terminate doesn't block, so if you then immediately accept the close event you will get your exception.
This is described in more detail in the documentation for the terminate slot
Proper QThread stop code is:
myThread->quit();
myThread->wait();
Also you have used moveToThread(this);
You need to moveToThread back to parent thread first.
For example your code is:
moveToThread(this);
start();
You need to save currentThread() before moveToThread() like this:
QThread *savedThread=currentThread();
moveToThread(this);
start();
And before quit or terminate you need to restore it:
moveToThread(savedThread);
quit();
wait();
You can put it on destructor of course.

Qt 5.3 Signals and Slots, Simple Function and Lambda Expression

I tried to Write a program using Qt 5.3 and I try to using signals and slots as practice. I wrote the following code (part of the code) :
void exitToWin()
{
exit(0);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
QMessageBox EndBox;
QObject::connect((EndBox.button(QMessageBox::Ok)),SIGNAL(clicked()),exitToWin);
w.show();
EndBox.show();
return a.exec();
}
I even change the declaration of the function to static and I checked the expression with parentheses and without them while I am writing the connect command. but although what Qt documented and what its IDE guided to. also I read here and I tested it.
Moreover I tried with lambda expression as below:
QObject::connect((EndBox.button(QMessageBox::Ok)),SIGNAL(clicked()),[=](){
exit(0);
});
but still I receive errors indicate "No matching function call".
And after all I have to say that I am using Microsoft Windows 7.
This works on Qt 5.3:
#include <QtWidgets>
void exitToWin()
{
exit(0);
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow w;
QMessageBox endBox;
endBox.addButton(QMessageBox::Ok); // (2)
endBox.connect(endBox.button(QMessageBox::Ok),
&QAbstractButton::clicked, exitToWin); // (1)
/* This works, too:
endBox.connect(endBox.button(QMessageBox::Ok),
&QAbstractButton::clicked,
[] () { exit(0); });
*/
w.show();
endBox.show();
return a.exec();
}
Here's why:
(1) You can use endBox's QObject to do the connection between the QAbstractButton's clicked signal and your exitToWin simple function. You also can't connect a SIGNAL to a simple function or a lambda, so we use the member function variety, instead.
(2) endBox doesn't actually get an OK button by default. When you mention it on line (1) in your code, it creates it, but not in time (apparently) to pass the pointer back to connect, so we create it first here.
Your code won't work for two reasons:
Firstly, QMessageBox does not have such a signal. See the documentation for the signals it does have.
Secondly, when making connections from a signal to a slot (or lambda function), you must define the function signatures, not specific values.
If a signal can pass a variety of values and you only want your slot to perform a certain function on a selection of those values (in this case, only if the value QMessageBox::Ok is passed) it is up to the slot to interrogate the values, not the connect statement.
Since the connect() method is from QObject it has to be called from a QObject child containing the Q_OBJECT macro in its declaration. Running qmake prepare the class to send signals and receive slots.

How to do things upon quitting a Qt app

To my understanding, the following will execute an application which will exit when all associated windows are closed.
int main(int argc, char *argv[])
{
QApplication cal(argc, argv); //Application instance
MainWindow window; //Create window in the stack
window.show(); //Show the window
return cal.exec(); //Execute event loop
}
This will also quit said application.
quitButton = new QPushButton("Quit", this);
connect(quitButton, SIGNAL(clicked()), QApplication::instance(), SLOT(quit()));
How should I go about cleaning up (closing hardware connections and libraries etc.) so that I can be sure everything that needs to happen happens no matter how the app it exited, nor at what point in execution it is exited?
I will have a library open throughout the whole app, and a connection to a USB device at most times. I am able to close this connection easily if the process runs its course, but I want the connection to be closed safely if somebody decides to hit quit or close all the windows before it is done.
There is a virtual function called closeEvent for a QWidget (see Documentation, which is called when the widgets close() operation is called.
Alternatively, if you don't want to have your own Base widget, you can hook yourself to the signal QApplication::lastWindowClosed (see here). It is emitted when the last visible window of your application closes.
You can do the following:
int main(int argc, char *argv[])
{
QApplication cal(argc, argv);
// Allocate resources
int ret = cal.exec(); // start the event loop and wait until it quits
// Free the resources
return ret;
}
The proper C++ way of doing it is:
Ensuring that all of your object instances get destructed.
Ensuring that any resources you hold are held via RAII.
Then you don't need to do anything special. As the objects get destructed when main returns, things get cleaned up.
For example:
int main(int argc, char ** argv) {
QApplication app(argc, argv);
QObject foo;
QObject * bar = new QObject(&app);
Widget w;
w.show();
return app.exec();
}
Here, both foo and bar are properly destructed before main returns. Now suppose you hold some non-memory resources, like a file:
class Worker : public QObject {
QFile m_file;
...
void doSomething() {
if (m_file.open()) {
...
}
// No file closing!
}
};
int main(int argc, char ** argv) {
QApplication app(argc, argv);
Worker foo;
Widget w;
w.show();
return app.exec();
}
Again, the file gets closed before main returns.
That's how RAII works, in a nutshell. If you have your own classes that wrap OS or other resources, simply ensure that such resources are freed when the classes get destructed - and that the classes are always destructible (it's always safe to destruct them). My pet peeve is QThread - it breaks this expectation, and you have to implement a wrapper to fix it.
For resources that you need to allocate on the heap, you're supposed to be using smart pointers or QObject memory management.
There is a QApplication signal that you can use for cleaning up before the application quits:
QObject::connect(&app, SIGNAL(aboutToQuit()), &MyCleaner, SLOT(cleanUp()));
Have fun!