From 2159ea0cfbc92a2892bb391f981d90456f9a752e Mon Sep 17 00:00:00 2001 From: Jordan Sherer Date: Fri, 22 Nov 2019 15:00:06 -0500 Subject: [PATCH] Updated decoder subprocess error handling to restart instead of crash the app --- Decoder.cpp | 16 ++++----- Decoder.h | 27 ++++++++++---- mainwindow.cpp | 96 +++++++++++++++++++++++++++++++------------------- mainwindow.h | 4 +-- 4 files changed, 91 insertions(+), 52 deletions(-) diff --git a/Decoder.cpp b/Decoder.cpp index f863edc..9d10799 100644 --- a/Decoder.cpp +++ b/Decoder.cpp @@ -91,15 +91,15 @@ void Decoder::processQuit(){ } // -void Decoder::processError(int errorCode){ - if(JS8_DEBUG_DECODE) qDebug() << "decoder process error" << errorCode; - emit error(errorCode); +void Decoder::processError(int errorCode, QString errorString){ + if(JS8_DEBUG_DECODE) qDebug() << "decoder process error" << errorCode << errorString; + emit error(errorCode, errorString); } // -void Decoder::processFinished(int exitCode, int statusCode){ - if(JS8_DEBUG_DECODE) qDebug() << "decoder process finished" << exitCode << statusCode; - emit finished(exitCode, statusCode); +void Decoder::processFinished(int exitCode, int statusCode, QString errorString){ + if(JS8_DEBUG_DECODE) qDebug() << "decoder process finished" << exitCode << statusCode << errorString; + emit finished(exitCode, statusCode, errorString); } //////////////////////////////////////// @@ -138,12 +138,12 @@ void Worker::start(QString path, QStringList args){ connect(proc, static_cast (&QProcess::error), [this, proc] (QProcess::ProcessError errorCode) { - emit error(int(errorCode)); + emit error(int(errorCode), proc->errorString()); }); connect(proc, static_cast (&QProcess::finished), [this, proc] (int exitCode, QProcess::ExitStatus status) { - emit finished(exitCode, int(status)); + emit finished(exitCode, int(status), QString{proc->readAllStandardError()}); }); QProcessEnvironment env {QProcessEnvironment::systemEnvironment ()}; diff --git a/Decoder.h b/Decoder.h index a267e90..3a95818 100644 --- a/Decoder.h +++ b/Decoder.h @@ -21,13 +21,14 @@ public slots: void start(QString path, QStringList args); void quit(); + QProcess* process() const { return m_proc.data(); } private: void setProcess(QProcess *proc, int msecs=1000); signals: void ready(QByteArray t); - void error(int errorCode); - void finished(int exitCode, int statusCode); + void error(int errorCode, QString errorString); + void finished(int exitCode, int statusCode, QString errorString); private: QScopedPointer m_proc; @@ -44,6 +45,20 @@ public: void lock(); void unlock(); + QString program() const { + if(!m_worker.isNull() && m_worker->process() != nullptr){ + return m_worker->process()->program(); + } + return {}; + } + + QStringList arguments() const { + if(!m_worker.isNull() && m_worker->process() != nullptr){ + return m_worker->process()->arguments(); + } + return {}; + } + private: Worker* createWorker(); @@ -56,16 +71,16 @@ public slots: void processReady(QByteArray t); void processQuit(); - void processError(int errorCode); - void processFinished(int exitCode, int statusCode); + void processError(int errorCode, QString errorString); + void processFinished(int exitCode, int statusCode, QString errorString); signals: void startWorker(QString path, QStringList args); void quitWorker(); void ready(QByteArray t); - void error(int errorCode); - void finished(int exitCode, int statusCode); + void error(int errorCode, QString errorString); + void finished(int exitCode, int statusCode, QString errorString); private: QPointer m_worker; diff --git a/mainwindow.cpp b/mainwindow.cpp index 0429d26..e966e0b 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -542,6 +542,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, //connect (&m_decodeThread, &QThread::finished, m_notification, &QObject::deleteLater); //connect(this, &MainWindow::decodedLineReady, this, &MainWindow::processDecodedLine); connect(&m_decoder, &Decoder::ready, this, &MainWindow::processDecodedLine); + connect(&m_decoder, &Decoder::error, this, [this](int errorCode, QString errorString){ + subProcessError(m_decoder.program(), m_decoder.arguments(), errorCode, errorString); + }); + connect(&m_decoder, &Decoder::finished, this, [this](int exitCode, int statusCode, QString errorString){ + subProcessFailed(m_decoder.program(), m_decoder.arguments(), exitCode, statusCode, errorString); + }); + on_EraseButton_clicked (); @@ -1617,6 +1624,10 @@ void MainWindow::initDecoderSubprocess(){ if(m_decoderBusy){ decodeBusy(false); } + + if(!m_valid){ + m_valid = true; + } } QPair, int> splitVersion(QString v){ @@ -3484,46 +3495,59 @@ void MainWindow::setup_status_bar (bool vhf) } } -void MainWindow::subProcessFailed (QProcess * process, int exit_code, QProcess::ExitStatus status) -{ - if (m_valid && (exit_code || QProcess::NormalExit != status)) - { - QStringList arguments; - for (auto argument: process->arguments ()) - { - if (argument.contains (' ')) argument = '"' + argument + '"'; - arguments << argument; - } - if (m_splash && m_splash->isVisible ()) m_splash->hide (); - MessageBox::critical_message (this, tr ("Subprocess Error") - , tr ("Subprocess failed with exit code %1") - .arg (exit_code) - , tr ("Running: %1\n%2") - .arg (process->program () + ' ' + arguments.join (' ')) - .arg (QString {process->readAllStandardError()})); - QTimer::singleShot (0, this, SLOT (close ())); - m_valid = false; // ensures exit if still constructing +void MainWindow::subProcessFailed (QString program, QStringList args, int exitCode, int status, QString errorString){ + if(!m_valid){ + return; } + + if(!exitCode || QProcess::NormalExit == QProcess::ExitStatus(status)){ + return; + } + + // surpress any other process notifications until restart + m_valid = false; + + QStringList arguments; + for (auto argument: args){ + if (argument.contains (' ')) argument = '"' + argument + '"'; + arguments << argument; + } + + if (m_splash && m_splash->isVisible ()) m_splash->hide (); + + MessageBox::critical_message (this, tr ("Subprocess Error") + , tr ("Subprocess failed with exit code %1 and will restart.") + .arg (exitCode) + , tr ("Running: %1\n%2") + .arg (program + ' ' + arguments.join (' ')) + .arg (errorString)); + + initDecoderSubprocess(); } -void MainWindow::subProcessError (QProcess * process, QProcess::ProcessError) -{ - if (m_valid) - { - QStringList arguments; - for (auto argument: process->arguments ()) - { - if (argument.contains (' ')) argument = '"' + argument + '"'; - arguments << argument; - } - if (m_splash && m_splash->isVisible ()) m_splash->hide (); - MessageBox::critical_message (this, tr ("Subprocess error") - , tr ("Running: %1\n%2") - .arg (process->program () + ' ' + arguments.join (' ')) - .arg (process->errorString ())); - QTimer::singleShot (0, this, SLOT (close ())); - m_valid = false; // ensures exit if still constructing +void MainWindow::subProcessError (QString program, QStringList args, int errorCode, QString errorString){ + if(!m_valid){ + return; } + + // surpress any other process notifications until process restart + m_valid = false; + + QStringList arguments; + for(auto argument: args){ + if (argument.contains (' ')) argument = '"' + argument + '"'; + arguments << argument; + } + + if (m_splash && m_splash->isVisible ()) m_splash->hide (); + + MessageBox::critical_message (this, tr ("Subprocess error") + , tr ("Subprocess errored with code %1 and will restart.").arg(errorCode) + , tr ("Running: %1\n%2") + .arg (program + ' ' + arguments.join (' ')) + .arg (errorString)); + + initDecoderSubprocess(); } void MainWindow::closeEvent(QCloseEvent * e) diff --git a/mainwindow.h b/mainwindow.h index 63f0abf..f9f77bf 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -1029,8 +1029,8 @@ private: void resetAutomaticIntervalTransmissions(bool stopCQ, bool stopHB); void resetCQTimer(bool stop); void resetHeartbeatTimer(bool stop); - void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus); - void subProcessError (QProcess *, QProcess::ProcessError); + void subProcessFailed (QString program, QStringList args, int exitCode, int status, QString errorString); + void subProcessError (QString program, QStringList arguments, int errorCode, QString errorString); void statusUpdate () const; void update_watchdog_label (); void on_the_minute ();