Proper usage of QProcess

qprocess, qt

Solution

You don't need to `waitForFinished()`, you'll receive the signal about it, so why wait? Instead, you might want to `waitForStarted()` in `launch()` to be sure that the process has started successfully. Of course in this case you'll need to change the way you use your `Launcher` - don't destroy it just after `launch()`.

You don't need to `terminate()`/`kill()` the process if it has finished, only if you need to stop it prematurely. You may delete it when you receive `finished()` or `error()` signal using `process_->deleteLater()` (you can't just `delete process_` while you are in the slot) or in your `~Launcher()`, providing that it won't be called until the process is finished.

Problem

- Platform: Qt 4.8.2, Win 7 Please consider the following logic flow: ``` 1. App started 2. functionA() triggered 3. the app periodically capture some images to external files 4. end of functionA() 5. the app create a video from captured images, using ffmpeg as external program 6. [step 2 -> step 5] may be repeated. 7. App quit ``` To achieve the flow, I use QProcess to start external program for me to join the images, but I got confused with the proper usage pattern of QProcess. (I don't care about the console messages of ffmpeg, i determine the success of step 5 by checking if the video file is created.) Attempt 1 ``` void MyWidget::createAVI() { checkAndDeleteAVI(); process = new QProcess(this); // process_ defined as class member; process->start("ffmpeg -f images2 ...."); process->waitForFinished(-1); // (a) // (b) } ``` At (a), I read the documentation the this call can freeze the main GUI, so should I call from QThread/QRunnable? At (b), am I missed something here? as when I attempt to close the app, (step 7 in the flow), the app crashes, and I thought that the spawned QProcess is not properly released. Attempt 2 I wrote a wrapper class of QProcess as follow: Launcher.h ``` class Launcher : public QObject { Q_OBJECT public: /** constructor */ explicit Launcher(QObject *parent = 0); /** destructor */ ~Launcher() { if (started_ && process_->state() != QProcess::NotRunning) process_->kill(); } // end_dtor(Launcher) Q_SIGNALS: void feedbackLog(QString log); public Q_SLOTS: void launch(QString program, QStringList argList); private: QProcess * process_; bool started_; private Q_SLOTS: void error(QProcess::ProcessError error); void finished(int exitCode, QProcess::ExitStatus status); void stateChanged(QProcess::ProcessState state); }; // end_class(Launcher) #endif // LAUNCHER_H ``` Launcher.cpp ``` #include "launcher.h" #include <QCoreApplication> #include <QtDebug> Launcher::Launcher(QObject *parent) : QObject(parent), started_(false) { process_ = new QProcess(this); connect(process_, SIGNAL(error(QProcess::ProcessError)), SLOT(error(QProcess::ProcessError))); connect(process_, SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(finished(int, QProcess::ExitStatus))); connect(process_, SIGNAL(stateChanged(QProcess::ProcessState)), SLOT(stateChanged(QProcess::ProcessState))); } // end_ctor(ExternalLauncher) void Launcher::launch(QString program, QStringList argList) { started_ = true; process_->start(program, argList); process_->waitForFinished(-1); // (c) Q_EMIT feedbackLog(process_->readAllStandardOutput()); process_->close(); } // end Launcher::launch() void Launcher::error(QProcess::ProcessError error) { /* just feedback some text about the error */ } // end_slot(Launcher::error) void Launcher::finished(int exitCode, QProcess::ExitStatus status) { started_ = false; /* feedback some text about finished */ } // end_slot (Launcher::finished) void Launcher::stateChanged(QProcess::ProcessState state) { qDebug() << "Luancher::stateChanged" << state; } ``` How I use the Launcher: ``` void MyWidget::createAVI() { checkAndDeleteAVI(); launcher_.launch("ffmpeg", "argsList"); // launcher_ defined as class member; } ``` So, at (c), is it unnecessary to waitForFinished()? (as I read some info that I should not mix up waitForXXX() and signal/slot framework for QProcess) Also, is there something I missed for the Launcher class, as I also experience app crash when using this approach. Main question: In general, when to call QProcess::terminate() / QProcess::kill(), and when to delete the QProcess object? Thanks

Original source