add TerminationTimeout timeout options
This commit is contained in:
parent
b34482ae97
commit
2af86f0524
4 changed files with 64 additions and 11 deletions
|
@ -21,16 +21,21 @@
|
|||
#include "SMSubProcess.h"
|
||||
#include "smsub.h"
|
||||
|
||||
SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory)
|
||||
SMSubProcess::SMSubProcess(const QString &executable, const QStringList &arguments, const QString &workingDirectory, const int &termTimeout) :
|
||||
termTimeout(termTimeout)
|
||||
{
|
||||
// Set process executable, arguments and working directory
|
||||
process.setProgram(executable);
|
||||
process.setArguments(arguments);
|
||||
process.setWorkingDirectory(workingDirectory);
|
||||
|
||||
// stdout and stderr in same IO stream
|
||||
process.setProcessChannelMode(QProcess::MergedChannels);
|
||||
|
||||
QObject::connect(&process, SIGNAL(readyRead()), this, SLOT(readyRead()));
|
||||
QObject::connect(&process, SIGNAL(finished(int)), this, SLOT(processExit(int)));
|
||||
QObject::connect(&process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(processError(QProcess::ProcessError)));
|
||||
// Connect process signal handlers
|
||||
QObject::connect(&process, &QProcess::readyRead, this, &SMSubProcess::readyRead);
|
||||
QObject::connect(&process, &QProcess::errorOccurred, this, &SMSubProcess::processError);
|
||||
QObject::connect(&process, QOverload<int>::of(&QProcess::finished), this, &SMSubProcess::processExit);
|
||||
}
|
||||
|
||||
void SMSubProcess::start()
|
||||
|
@ -69,10 +74,10 @@ void SMSubProcess::processError(QProcess::ProcessError error)
|
|||
|
||||
void SMSubProcess::aboutToQuit()
|
||||
{
|
||||
// Main process terminated
|
||||
// Main process terminated, terminate subprocess with set timeout
|
||||
if (process.state() == QProcess::Running) {
|
||||
process.terminate();
|
||||
if (!process.waitForFinished(60000)) {
|
||||
if (!process.waitForFinished(termTimeout)) {
|
||||
QTextStream(stderr) << "Failed to terminate process!" << endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,11 +26,12 @@ class SMSubProcess : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SMSubProcess(const QString &executable, const QStringList &arguments, const QString& workingDirectory);
|
||||
SMSubProcess(const QString &executable, const QStringList &arguments, const QString& workingDirectory, const int &termTimeout = 60000);
|
||||
void start();
|
||||
|
||||
private:
|
||||
QProcess process;
|
||||
int termTimeout;
|
||||
|
||||
public slots:
|
||||
void aboutToQuit();
|
||||
|
|
|
@ -55,6 +55,8 @@ void SMSubServer::readyRead()
|
|||
bool isAuthenticated = socket->property("Authenticated").toBool();
|
||||
while (socket->canReadLine()) {
|
||||
const QByteArray readData = socket->readLine().trimmed();
|
||||
|
||||
// Only allow commands being sent if authenticated
|
||||
if (likely(isAuthenticated)) {
|
||||
if (readData.startsWith("+dbg")) {
|
||||
socket->setProperty("ReceiveDbgMsg", true);
|
||||
|
@ -103,7 +105,9 @@ void SMSubServer::readyRead()
|
|||
}
|
||||
}
|
||||
else {
|
||||
// Authenticate when token is valid, otherwise disconnect
|
||||
if (unlikely(tokens.contains(QString::fromUtf8(readData)))) {
|
||||
// Set client as authenticated and add it to vector
|
||||
socket->setProperty("Authenticated", true);
|
||||
socket->write("Login successful!\n");
|
||||
isAuthenticated = true;
|
||||
|
@ -159,6 +163,7 @@ void SMSubServer::writeOutput(const QByteArray &output)
|
|||
|
||||
void SMSubServer::registerToken(const QString &token)
|
||||
{
|
||||
// Register temporary token for a secure remote connection
|
||||
tokens << token;
|
||||
QTimer::singleShot(30000, [this, token]() {
|
||||
tokens.removeAll(token);
|
||||
|
|
50
main.cpp
50
main.cpp
|
@ -39,7 +39,24 @@
|
|||
#ifdef Q_OS_UNIX
|
||||
void catchUnixSignals(std::initializer_list<int> quitSignals) {
|
||||
auto handler = [](int sig) -> void {
|
||||
QTextStream(stderr) << "Received Unix signal: " << sig << endl;
|
||||
QString unixSignal;
|
||||
switch (sig) {
|
||||
case SIGINT:
|
||||
unixSignal = QLatin1String("SIGINT");
|
||||
break;
|
||||
case SIGHUP:
|
||||
unixSignal = QLatin1String("SIGHUP");
|
||||
break;
|
||||
case SIGQUIT:
|
||||
unixSignal = QLatin1String("SIGQUIT");
|
||||
break;
|
||||
case SIGTERM:
|
||||
unixSignal = QLatin1String("SIGTERM");
|
||||
break;
|
||||
default:
|
||||
unixSignal = QString::number(sig);
|
||||
}
|
||||
QTextStream(stderr) << "Received Unix signal: " << unixSignal << endl;
|
||||
QCoreApplication::quit();
|
||||
};
|
||||
|
||||
|
@ -62,10 +79,10 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
a.setApplicationName("Server Manager Subprocess");
|
||||
a.setApplicationVersion("0.2");
|
||||
a.setApplicationVersion("0.2.1");
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
catchUnixSignals({SIGQUIT, SIGINT, SIGTERM, SIGHUP});
|
||||
catchUnixSignals({SIGINT, SIGHUP, SIGQUIT, SIGTERM});
|
||||
#endif
|
||||
|
||||
QCommandLineParser commandLineParser;
|
||||
|
@ -95,6 +112,9 @@ int main(int argc, char *argv[])
|
|||
#endif
|
||||
commandLineParser.addOption(subprocessRemoteSocket);
|
||||
|
||||
QCommandLineOption processTimeout("timeout", "SMSub termination timeout.", "timeout");
|
||||
commandLineParser.addOption(processTimeout);
|
||||
|
||||
commandLineParser.process(a);
|
||||
|
||||
if (unlikely(commandLineParser.isSet(processManifest) && commandLineParser.isSet(processExecutable))) {
|
||||
|
@ -102,6 +122,17 @@ int main(int argc, char *argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
bool timeoutSet = false;
|
||||
int termTimeout = 60000;
|
||||
if (unlikely(commandLineParser.isSet(processTimeout))) {
|
||||
bool ok;
|
||||
const int _termTimeout = commandLineParser.value(processTimeout).toInt(&ok);
|
||||
if (ok) {
|
||||
termTimeout = _termTimeout;
|
||||
timeoutSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
QString executable;
|
||||
QString workingDirectory;
|
||||
QStringList argumentList;
|
||||
|
@ -158,6 +189,17 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if (unlikely(!timeoutSet && jsonObject.contains("TerminationTimeout"))) {
|
||||
const QJsonValue jsonTimeout = jsonObject.value("TerminationTimeout");
|
||||
if (unlikely(!jsonTimeout.isDouble())) {
|
||||
termTimeout = qRound(jsonTimeout.toDouble());
|
||||
}
|
||||
else {
|
||||
QTextStream(stderr) << "Termination Timeout is not a number in manifest, aborting!" << endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
manifestFile.close();
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +259,7 @@ int main(int argc, char *argv[])
|
|||
localSettings.canRegister = false;
|
||||
}
|
||||
|
||||
SMSubProcess subProcess(executable, argumentList, workingDirectory);
|
||||
SMSubProcess subProcess(executable, argumentList, workingDirectory, termTimeout);
|
||||
|
||||
QObject::connect(&subProcess, &SMSubProcess::outputWritten, &subLocal, &SMSubServer::writeOutput);
|
||||
QObject::connect(&subLocal, &SMSubServer::inputWritten, &subProcess, &SMSubProcess::writeInput);
|
||||
|
|
Loading…
Reference in a new issue