njahnke
njahnke

Reputation: 1387

QProcess::terminate() doesn't work with simple Qt app as child process under Windows XP

First, my simple Qt app that I will start from a QProcess object:

#include <QtGui>

class LOLProcess : public QMainWindow {
    Q_OBJECT
public:
    LOLProcess(QWidget *parent = 0);
    ~LOLProcess();
protected:
    void closeEvent(QCloseEvent *);
};

LOLProcess::LOLProcess(QWidget *parent) : QMainWindow(parent) {
}
LOLProcess::~LOLProcess() {
    qDebug() << "~LOLProcess()";
}
void LOLProcess::closeEvent(QCloseEvent *) {
    qDebug() << "closeEvent()";
}

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    LOLProcess w;
    w.show();
    return a.exec();
}

Now, the Qt app with the QProcess object:

#include <QtGui>

class MainWindow : public QMainWindow {
    Q_OBJECT
public:
    MainWindow(QWidget *parent = 0);
    QProcess process;
public slots:
    void close_down();
};

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
    process.start("../../lolprocess-build-desktop-Qt_4_8_1_for_Desktop_-_MinGW__Qt_SDK__Release/release/lolprocess.exe");
    QTimer::singleShot(3000, this, SLOT(close_down()));
}

void MainWindow::close_down() {
    process.terminate();
    while (!process.waitForFinished(500)) {
    qDebug() << process.readAllStandardError();
    qDebug() << process.readAllStandardOutput();
    }
    qDebug() << process.waitForFinished(5000);
    qDebug() << (process.state() == QProcess::Running);
}

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    QDir::setCurrent(QCoreApplication::applicationDirPath());
    MainWindow w;
    w.show();
    return a.exec();
}

Behavior: terminate() causes the child process's window to vanish (and from the XP taskbar), but the process is still running according to taskman. The while (!process.waitForFinished(500)) loops forever since the QProcess object never emits finished(). Surprisingly, I get nothing over stdin or stderr from the child process (it prints only the empty string for the QProcess::readAllStandard...() calls) which seems odd because the child process's top window closing makes me think closeEvent() was called in the child process.

Terminating the child process with QProcess::kill() works, but I don't want to use it because it doesn't give the child process a chance to clean up before exiting.

Interestingly, this same code works correctly under Qt 4.7.4 and OS X 10.6.x - terminate() causes the child process to exit cleanly, so I'm not sure what I'm doing wrong under XP. Thanks.

Upvotes: 1

Views: 2417

Answers (1)

j_kubik
j_kubik

Reputation: 6181

Try now:

#include <QtGui>

class LOLProcess : public QMainWindow {
    Q_OBJECT
public:
    LOLProcess(QWidget *parent = 0);
    ~LOLProcess();
protected:
    void closeEvent(QCloseEvent *);

public slots:
    void lastWindowClosed();
};

LOLProcess::LOLProcess(QWidget *parent) : QMainWindow(parent) {
}
LOLProcess::~LOLProcess() {
    qDebug() << "~LOLProcess()";
}
void LOLProcess::closeEvent(QCloseEvent *) {
    qDebug() << "closeEvent()";
}

void LOLProcess::lastWindowClosed (){
    QApplication::quit();
}

int main(int argc, char *argv[]) {
    QApplication a(argc, argv);
    LOLProcess w;
    QObject::connect(&a, SIGNAL(lastWindowClosed()), &w, SLOT(lastWindowClosed()));
    w.show();
    return a.exec();
}

This should not be necesary. Seems like some really weird quirk/bug in qt - when I have more time I will investigate it further.

Upvotes: 2

Related Questions