Improved subprocess handling and error reporting

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6675 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2016-05-07 19:32:52 +00:00
parent a45ea3cdff
commit cc8d2130c6
2 changed files with 81 additions and 78 deletions

View File

@ -143,6 +143,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
unsigned downSampleFactor, QNetworkAccessManager * network_manager,
QWidget *parent) :
QMainWindow(parent),
m_valid {true},
m_dataDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)},
m_revision {revision ()},
m_multiple {multiple},
@ -382,17 +383,34 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
setWindowTitle (program_title ());
createStatusBar();
connect(&proc_jt9, SIGNAL(readyReadStandardOutput()),this, SLOT(readFromStdout()));
connect(&proc_jt9, SIGNAL(error(QProcess::ProcessError)),this, SLOT(jt9_error(QProcess::ProcessError)));
connect(&proc_jt9, SIGNAL(readyReadStandardError()),this, SLOT(readFromStderr()));
connect(&proc_jt9, &QProcess::readyReadStandardOutput, this, &MainWindow::readFromStdout);
connect(&proc_jt9, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
[this] (QProcess::ProcessError error) {
subProcessError (&proc_jt9, error);
});
connect(&proc_jt9, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
[this] (int exitCode, QProcess::ExitStatus status) {
subProcessFailed (&proc_jt9, exitCode, status);
});
connect(&p1, SIGNAL(readyReadStandardOutput()),this, SLOT(p1ReadFromStdout()));
connect(&p1, SIGNAL(error(QProcess::ProcessError)),this, SLOT(p1Error(QProcess::ProcessError)));
connect(&p1, SIGNAL(readyReadStandardError()),this, SLOT(p1ReadFromStderr()));
connect(&p1, &QProcess::readyReadStandardOutput, this, &MainWindow::p1ReadFromStdout);
connect(&proc_jt9, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
[this] (QProcess::ProcessError error) {
subProcessError (&p1, error);
});
connect(&p1, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
[this] (int exitCode, QProcess::ExitStatus status) {
subProcessFailed (&p1, exitCode, status);
});
// connect(&p3, SIGNAL(readyReadStandardOutput()),this, SLOT(p3ReadFromStdout()));
connect(&p3, SIGNAL(error(QProcess::ProcessError)),this, SLOT(p3Error(QProcess::ProcessError)));
connect(&p3, SIGNAL(readyReadStandardError()),this, SLOT(p3ReadFromStderr()));
connect(&p3, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
[this] (QProcess::ProcessError error) {
subProcessError (&p3, error);
});
connect(&p3, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
[this] (int exitCode, QProcess::ExitStatus status) {
subProcessFailed (&p3, exitCode, status);
});
// Hook up working frequencies.
ui->bandComboBox->setModel (m_config.frequencies ());
@ -485,7 +503,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_txFirst=false;
m_btxok=false;
m_restart=false;
m_killAll=false;
m_widebandDecode=false;
m_ntx=1;
@ -706,6 +723,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
int ntr[]={5,10,15,30};
m_TRperiod=ntr[m_TRindex-11];
}
// this must be the last statement of constructor
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
}
//--------------------------------------------------- MainWindow destructor
@ -1464,6 +1484,43 @@ void MainWindow::createStatusBar() //createStatusBar
progressBar->setFormat("%v/%m");
}
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;
}
msgBox (tr ("Subprocess failed with exit code %1\nRunning:%2\n%3")
.arg (exit_code)
.arg (process->program () + ' ' + arguments.join (' '))
.arg (QString {process->readAllStandardError()}));
close ();
m_valid = false; // ensures exit if still constructing
}
}
void MainWindow::subProcessError (QProcess * process, QProcess::ProcessError)
{
if (m_valid)
{
QStringList arguments;
for (auto argument: process->arguments ())
{
if (argument.contains (' ')) argument = '"' + argument + '"';
arguments << argument;
}
msgBox (tr ("Subprocess error\nRunning: %1\n%2")
.arg (process->program () + ' ' + arguments.join (' '))
.arg (process->errorString ()));
close ();
m_valid = false; // ensures exit if still constructing
}
}
void MainWindow::closeEvent(QCloseEvent * e)
{
m_config.transceiver_offline ();
@ -1474,7 +1531,6 @@ void MainWindow::closeEvent(QCloseEvent * e)
m_mouseCmnds.reset ();
killFile ();
m_killAll=true;
mem_jt9->detach();
QFile quitFile {m_config.temp_dir ().absoluteFilePath (".quit")};
quitFile.open(QIODevice::ReadWrite);
@ -1992,19 +2048,16 @@ void::MainWindow::fast_decode_done()
ui->DecodeButton->setChecked (false);
}
void MainWindow::jt9_error (QProcess::ProcessError e)
void MainWindow::decodeDone ()
{
if(!m_killAll) {
msgBox("Error starting or running\n" + m_appDir + "/jt9 -s");
qDebug() << e; // silence compiler warning
exit(1);
}
}
void MainWindow::readFromStderr() //readFromStderr
{
QByteArray t=proc_jt9.readAllStandardError();
msgBox(t);
dec_data.params.nagain=0;
dec_data.params.ndiskdat=0;
m_nclearave=0;
QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.open(QIODevice::ReadWrite);
ui->DecodeButton->setChecked (false);
decodeBusy(false);
m_RxLog=0;
m_blankLine=true;
}
void MainWindow::readFromStdout() //readFromStdout
@ -2033,15 +2086,8 @@ void MainWindow::readFromStdout() //readFromStdout
if(t.indexOf("<DecodeFinished>") >= 0) {
m_bDecoded = (t.mid(23,1).toInt()==1);
if(!m_diskData) killFileTimer->start (3*1000*m_TRperiod/4); //Kill in 45 s
dec_data.params.nagain=0;
dec_data.params.ndiskdat=0;
m_nclearave=0;
QFile {m_config.temp_dir ().absoluteFilePath (".lock")}.open(QIODevice::ReadWrite);
ui->DecodeButton->setChecked (false);
decodeBusy(false);
m_RxLog=0;
decodeDone ();
m_startAnother=m_loopall;
m_blankLine=true;
return;
} else {
QFile f {m_dataDir.absoluteFilePath ("ALL.TXT")};
@ -5003,21 +5049,6 @@ void MainWindow::on_syncSpinBox_valueChanged(int n)
m_minSync=n;
}
void MainWindow::p1ReadFromStderr() //p1readFromStderr
{
QByteArray t=p1.readAllStandardError();
msgBox(t);
}
void MainWindow::p1Error (QProcess::ProcessError e)
{
if(!m_killAll) {
msgBox("Error starting or running\n" + m_appDir + "/wsprd");
qDebug() << e; // silence compiler warning
exit(1);
}
}
void MainWindow::p1ReadFromStdout() //p1readFromStdout
{
QString t1;
@ -5180,30 +5211,6 @@ void MainWindow::uploadResponse(QString response)
}
}
void MainWindow::p3ReadFromStdout() //p3readFromStdout
{
QByteArray t=p3.readAllStandardOutput();
if(t.length()>0) {
msgBox("user_hardware stdout:\n\n"+t+"\n"+m_cmnd);
}
}
void MainWindow::p3ReadFromStderr() //p3readFromStderr
{
QByteArray t=p3.readAllStandardError();
if(t.length()>0) {
msgBox("user_hardware stderr:\n\n"+t+"\n"+m_cmnd);
}
}
void MainWindow::p3Error(QProcess::ProcessError e) //p3rror
{
msgBox("Error attempting to run user_hardware.\n\n"+m_cmnd);
qDebug() << e; // silence compiler warning
}
void MainWindow::on_TxPowerComboBox_currentIndexChanged(const QString &arg1)
{
int i1=arg1.indexOf(" ");

View File

@ -100,11 +100,7 @@ public slots:
void doubleClickOnCall(bool shift, bool ctrl);
void doubleClickOnCall2(bool shift, bool ctrl);
void readFromStdout();
void readFromStderr();
void jt9_error(QProcess::ProcessError);
void p1ReadFromStdout();
void p1ReadFromStderr();
void p1Error(QProcess::ProcessError);
void setXIT(int n, Frequency base = 0u);
void setFreq4(int rxFreq, int txFreq);
void msgAvgDecode2();
@ -233,9 +229,6 @@ private slots:
void TxAgain();
void RxQSY();
void uploadResponse(QString response);
void p3ReadFromStdout();
void p3ReadFromStderr();
void p3Error(QProcess::ProcessError e);
void on_WSPRfreqSpinBox_valueChanged(int n);
void on_pbTxNext_clicked(bool b);
void on_actionEcho_Graph_triggered();
@ -277,6 +270,7 @@ private:
private:
void astroUpdate ();
bool m_valid;
QDir m_dataDir;
QString m_revision;
bool m_multiple;
@ -382,7 +376,6 @@ private:
bool m_widebandDecode;
bool m_call3Modified;
bool m_dataAvailable;
bool m_killAll;
bool m_bDecoded;
bool m_monitorStartOFF;
bool m_pskReporterInit;
@ -576,6 +569,9 @@ private:
void CQRxFreq();
void save_wave_file (QString const& name, short const * data, int seconds) const;
void read_wav_file (QString const& fname);
void decodeDone ();
void subProcessFailed (QProcess *, int exit_code, QProcess::ExitStatus);
void subProcessError (QProcess *, QProcess::ProcessError);
};
extern int killbyname(const char* progName);