How to restart a qt application after crashing? - qt

Is it possible to restart a qt application after its crashing? Just like those windows service which will restart on its own. If so, how could I do it? I have tried code like this:
#define RESTART_CODE 1000
int main(int argc, char *argv[])
{
int return_from_event_loop_code;
QPointer<QApplication> app;
QPointer<MainWindow> main_window;
do
{
if(app) delete app;
if(main_window) delete main_window;
app = new QApplication(argc, argv);
main_window = new MainWindow(app);
return_from_event_loop_code = app->exec();
}
while(return_from_event_loop_code==RESTART_CODE)
return return_from_event_loop_code;
}
But it is not working...
What should I do now?

create another qt application that runs your application.
#include <QApplication>
#include "QProcess"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QProcess aProcess;
QString exe = "Your process name with exact path";
QByteArray myOut;
while(1)
{
aProcess.start(exe);
//aProcess.waitForStarted();
//myOut = aProcess.readAllStandardOutput();
//printf("%s",myOut.constData());
aProcess.waitForFinished(-1);
//QString output(aProcess.readAllStandardOutput());
myOut = aProcess.readAllStandardOutput();
printf("%s",myOut.constData());
}
return a.exec();
}
this program will restart your app when it crashed or closed

You can use my open source library:
https://marketplace.qt.io/products/main-loop-wdt-for-qt-qml
It is a watchdog timer for the main loop and only works if the main loop freezes (double mutex lock, infinite loop, etc.), but it would not work in an application crash.

Related

Doctest and qapplication

I must integrate doctest lib to a QT core project (Qt5 exactly).
At a point, I need a qcoreapplication to run event loop.
But when I try implement my doctest main with a qcoreapplication it looks doctest context and qcoreapplication parasite themself.
Do there are some workarounds? like qeventloop without qcoreapplication? other ways?
Did someone have already encountered this kind of case with other test libs?
Thanks for answers ;)
Edit 1:
For confidentiality reason i can't share actual base code. But i have same issue with basic code.
At my actual point i fall in an infinite loop at the end of execution.
I may just miss something on QCoreApplication execution end.
#define DOCTEST_CONFIG_IMPLEMENT
#include <QDebug>
#include <QObject>
#include <QSignalSpy>
#include <QApplication>
#include <QEventLoop>
#include "../../Core/external/doctest/doctest.h"
TEST_CASE("Basic class") {
SUBCASE("2*2") {
qDebug()<<"2*2";
CHECK_EQ(2*2, 4);
}
SUBCASE("1+1") {
qDebug()<<"1+1";
CHECK_EQ(1+1, 2);
}
SUBCASE("Termination") {
qDebug()<<"End!!";
QCoreApplication::instance()->quit();
}
}
int main(int argc, char** argv) {
doctest::Context context;
// defaults
context.setOption("abort-after", 5);
context.setOption("order-by", "name");
QCoreApplication app (argc, argv);
context.applyCommandLine(argc, argv);
context.setOption("no-breaks", true);
int res = context.run();
if(context.shouldExit())
return res;
int client_stuff_return_code = 0;
return res + client_stuff_return_code + app.exec(); // the result from doctest is propagated here as well
}

how to read QByteArray and run as Detached process in qt?

I'm trying to run the hardcoded base64 .exe file in a Detached process.
What I'm trying now is:
void Read(QString file){
QProcess process;
process.startDetached(file);
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QByteArray exe = QByteArray::fromBase64("TVqQAAMAAAAEAAAA...."); //base64 of .exe file
QString s = exe.data();
qDebug() << s ;
Read(s);
return a.exec();
}
not working, debug shows : "MZ?"

QDialog exec() can not exit process

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QDialog dlg;
dlg.exec();
return a.exec();
}
That's all my code, but when I close the window, The process isn't exit, it seems that drop in the loop a.exec().
Generally speaking, calling any exec is a bad idea, other than QCoreApplication::exec() or QDrag::exec(). The presence of exec() and waitForXxx() methods is an enticing trap for the unwary. Those methods are "easy" to use, but that ease comes at a price of hard to track bugs. Don't use them.
You should simply show the dialog:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMessageBox msg;
msg.setText("Hello");
msg.addButton(QMessageBox::Close);
msg.show();
return a.exec();
}
If you wish to wait for the dialog to be accepted or rejected, you should use the dialog's clickedButton slot. QMessageBox has a long-standing bug that makes the accepted and rejected signals useless :(
// https://github.com/KubaO/stackoverflown/tree/master/questions/messagebox-show-25545652
#include <QtGui>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <QtWidgets>
#endif
#include <functional>
[...]
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QMessageBox msg;
msg.setText("Continue?");
msg.addButton(QMessageBox::Yes);
msg.addButton(QMessageBox::No);
auto onClick = [&msg]() {
auto role = msg.buttonRole(msg.clickedButton());
if (role == QMessageBox::NoRole)
QApplication::quit();
if (role == QMessageBox::YesRole) {
auto label = new QLabel("I'm running");
label->setAttribute(Qt::WA_DeleteOnClose);
label->show();
}
};
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
QObject::connect(&msg, &QMessageBox::buttonClicked, onClick);
#else
QObject::connect(&msg, SIGNAL(buttonClicked(QAbstractButton*)),
new FunctorSlot{onClick, &msg}, SLOT(call()));
#endif
msg.show();
return app.exec();
}
#include "main.moc"
For Qt 4, you need the following helper:
// Qt 4 only
struct FunctorSlot : public QObject {
Q_OBJECT
public:
std::function<void()> callable;
template <typename Fun>
FunctorSlot(Fun && fun, QObject * parent = {}) :
QObject{parent}, callable{std::forward<Fun>(fun)} {}
Q_SLOT void call() {
callable();
}
};
Possible solution:
QApplication a(argc, argv);
QDialog dlg;
QTimer::singleShot( &dlg, 0, SLOT(exec()) );
return a.exec();
It will work well. First - application event loop will be started. Then dialog event loop will be executed. After closing of dialog, both dialog and application loop will be finished. Application loop will be terminated automatically (by default), when last window is closed.
But, as noted by #thuga - there are no reason to call exec(). It is enough to call show() method.

Remove application from memory

I am trying to close an application
#include <QtGui/QApplication>
#include "battle.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
battle w;
int x = 14;
if(x == 1)
{
w.show();
}
else if(x!=1)
{
qApp->exit(0);
//Remove application from memory...
}
return a.exec();
}
but if i go to windows processes,it is still there.What is the best way to remove the application from memory?.
Don't call a.exec() after you call qApp->exit(0).
What's inside battle.h? If you start a thread in the battle class, and closing the window does not stop it, then the process will remain in the task list even if you close the window.

QX11EmbedWidget and QX11EmbedContainer

Can one place an arbitrary program (firefox, openoffice, etc...) in a QX11EmbedContainer? The fllowing seems, to work
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QX11EmbedContainer container;
container.show();
QProcess * process = new QProcess(&container);
QString executable("xterm");
QStringList arguments;
arguments << "-into";
arguments << QString::number(container.winId());
process->start(executable, arguments);
int status = app.exec();
process->close();
return status;
}
but the next snippet launches a new window, not what I want
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QX11EmbedContainer container;
container.show();
QProcess * process = new QProcess(&container);
QString executable("konsole");
process->start(executable);
int status = app.exec();
process->close();
return status;
}
The first example work because xterm is able to reparent its top level widget (an X11 window). You tell it to do so with the argument -into <WinId>.
I don't know if Konsole can do that, i don't use it and the man page doesn't seem to talk about this.
But that doesn't mean it is not doable, the X Window system is very flexible and anyone can reparent another window (that's how windows managers add decorations to windows).
Take a look at man 3 XReparentWindow ;-)

Resources