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){
|
||||
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<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
|
||||
[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),
|
||||
[this, proc] (int exitCode, QProcess::ExitStatus status) {
|
||||
emit finished(exitCode, int(status));
|
||||
emit finished(exitCode, int(status), QString{proc->readAllStandardError()});
|
||||
});
|
||||
|
||||
QProcessEnvironment env {QProcessEnvironment::systemEnvironment ()};
|
||||
|
27
Decoder.h
27
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<QProcess> 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<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(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<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)
|
||||
{
|
||||
if (m_valid && (exit_code || QProcess::NormalExit != status))
|
||||
{
|
||||
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: process->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")
|
||||
.arg (exit_code)
|
||||
, tr ("Subprocess failed with exit code %1 and will restart.")
|
||||
.arg (exitCode)
|
||||
, 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
|
||||
}
|
||||
.arg (program + ' ' + arguments.join (' '))
|
||||
.arg (errorString));
|
||||
|
||||
initDecoderSubprocess();
|
||||
}
|
||||
|
||||
void MainWindow::subProcessError (QProcess * process, QProcess::ProcessError)
|
||||
{
|
||||
if (m_valid)
|
||||
{
|
||||
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: process->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 (process->program () + ' ' + arguments.join (' '))
|
||||
.arg (process->errorString ()));
|
||||
QTimer::singleShot (0, this, SLOT (close ()));
|
||||
m_valid = false; // ensures exit if still constructing
|
||||
}
|
||||
.arg (program + ' ' + arguments.join (' '))
|
||||
.arg (errorString));
|
||||
|
||||
initDecoderSubprocess();
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent * e)
|
||||
|
@ -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 ();
|
||||
|
Loading…
Reference in New Issue
Block a user