Updated decoder subprocess error handling to restart instead of crash the app
This commit is contained in:
parent
cb7f84d952
commit
2159ea0cfb
16
Decoder.cpp
16
Decoder.cpp
@ -91,15 +91,15 @@ void Decoder::processQuit(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
void Decoder::processError(int errorCode){
|
void Decoder::processError(int errorCode, QString errorString){
|
||||||
if(JS8_DEBUG_DECODE) qDebug() << "decoder process error" << errorCode;
|
if(JS8_DEBUG_DECODE) qDebug() << "decoder process error" << errorCode << errorString;
|
||||||
emit error(errorCode);
|
emit error(errorCode, errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
void Decoder::processFinished(int exitCode, int statusCode){
|
void Decoder::processFinished(int exitCode, int statusCode, QString errorString){
|
||||||
if(JS8_DEBUG_DECODE) qDebug() << "decoder process finished" << exitCode << statusCode;
|
if(JS8_DEBUG_DECODE) qDebug() << "decoder process finished" << exitCode << statusCode << errorString;
|
||||||
emit finished(exitCode, statusCode);
|
emit finished(exitCode, statusCode, errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////
|
////////////////////////////////////////
|
||||||
@ -138,12 +138,12 @@ void Worker::start(QString path, QStringList args){
|
|||||||
|
|
||||||
connect(proc, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
|
connect(proc, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
|
||||||
[this, proc] (QProcess::ProcessError errorCode) {
|
[this, proc] (QProcess::ProcessError errorCode) {
|
||||||
emit error(int(errorCode));
|
emit error(int(errorCode), proc->errorString());
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(proc, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
|
connect(proc, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
|
||||||
[this, proc] (int exitCode, QProcess::ExitStatus status) {
|
[this, proc] (int exitCode, QProcess::ExitStatus status) {
|
||||||
emit finished(exitCode, int(status));
|
emit finished(exitCode, int(status), QString{proc->readAllStandardError()});
|
||||||
});
|
});
|
||||||
|
|
||||||
QProcessEnvironment env {QProcessEnvironment::systemEnvironment ()};
|
QProcessEnvironment env {QProcessEnvironment::systemEnvironment ()};
|
||||||
|
27
Decoder.h
27
Decoder.h
@ -21,13 +21,14 @@ public slots:
|
|||||||
void start(QString path, QStringList args);
|
void start(QString path, QStringList args);
|
||||||
void quit();
|
void quit();
|
||||||
|
|
||||||
|
QProcess* process() const { return m_proc.data(); }
|
||||||
private:
|
private:
|
||||||
void setProcess(QProcess *proc, int msecs=1000);
|
void setProcess(QProcess *proc, int msecs=1000);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void ready(QByteArray t);
|
void ready(QByteArray t);
|
||||||
void error(int errorCode);
|
void error(int errorCode, QString errorString);
|
||||||
void finished(int exitCode, int statusCode);
|
void finished(int exitCode, int statusCode, QString errorString);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QScopedPointer<QProcess> m_proc;
|
QScopedPointer<QProcess> m_proc;
|
||||||
@ -44,6 +45,20 @@ public:
|
|||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
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:
|
private:
|
||||||
Worker* createWorker();
|
Worker* createWorker();
|
||||||
|
|
||||||
@ -56,16 +71,16 @@ public slots:
|
|||||||
void processReady(QByteArray t);
|
void processReady(QByteArray t);
|
||||||
void processQuit();
|
void processQuit();
|
||||||
|
|
||||||
void processError(int errorCode);
|
void processError(int errorCode, QString errorString);
|
||||||
void processFinished(int exitCode, int statusCode);
|
void processFinished(int exitCode, int statusCode, QString errorString);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void startWorker(QString path, QStringList args);
|
void startWorker(QString path, QStringList args);
|
||||||
void quitWorker();
|
void quitWorker();
|
||||||
|
|
||||||
void ready(QByteArray t);
|
void ready(QByteArray t);
|
||||||
void error(int errorCode);
|
void error(int errorCode, QString errorString);
|
||||||
void finished(int exitCode, int statusCode);
|
void finished(int exitCode, int statusCode, QString errorString);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPointer<Worker> m_worker;
|
QPointer<Worker> m_worker;
|
||||||
|
@ -542,6 +542,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
|||||||
//connect (&m_decodeThread, &QThread::finished, m_notification, &QObject::deleteLater);
|
//connect (&m_decodeThread, &QThread::finished, m_notification, &QObject::deleteLater);
|
||||||
//connect(this, &MainWindow::decodedLineReady, this, &MainWindow::processDecodedLine);
|
//connect(this, &MainWindow::decodedLineReady, this, &MainWindow::processDecodedLine);
|
||||||
connect(&m_decoder, &Decoder::ready, 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 ();
|
on_EraseButton_clicked ();
|
||||||
|
|
||||||
@ -1617,6 +1624,10 @@ void MainWindow::initDecoderSubprocess(){
|
|||||||
if(m_decoderBusy){
|
if(m_decoderBusy){
|
||||||
decodeBusy(false);
|
decodeBusy(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!m_valid){
|
||||||
|
m_valid = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPair<QPair<int, int>, int> splitVersion(QString v){
|
QPair<QPair<int, int>, 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)
|
void MainWindow::subProcessFailed (QString program, QStringList args, int exitCode, int status, QString errorString){
|
||||||
{
|
if(!m_valid){
|
||||||
if (m_valid && (exit_code || QProcess::NormalExit != status))
|
return;
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
void MainWindow::subProcessError (QString program, QStringList args, int errorCode, QString errorString){
|
||||||
{
|
if(!m_valid){
|
||||||
if (m_valid)
|
return;
|
||||||
{
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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)
|
void MainWindow::closeEvent(QCloseEvent * e)
|
||||||
|
@ -1029,8 +1029,8 @@ private:
|
|||||||
void resetAutomaticIntervalTransmissions(bool stopCQ, bool stopHB);
|
void resetAutomaticIntervalTransmissions(bool stopCQ, bool stopHB);
|
||||||
void resetCQTimer(bool stop);
|
void resetCQTimer(bool stop);
|
||||||
void resetHeartbeatTimer(bool stop);
|
void resetHeartbeatTimer(bool stop);
|
||||||
void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
|
void subProcessFailed (QString program, QStringList args, int exitCode, int status, QString errorString);
|
||||||
void subProcessError (QProcess *, QProcess::ProcessError);
|
void subProcessError (QString program, QStringList arguments, int errorCode, QString errorString);
|
||||||
void statusUpdate () const;
|
void statusUpdate () const;
|
||||||
void update_watchdog_label ();
|
void update_watchdog_label ();
|
||||||
void on_the_minute ();
|
void on_the_minute ();
|
||||||
|
Loading…
Reference in New Issue
Block a user