diff options
author | Petr Mrázek <peterix@gmail.com> | 2016-11-03 01:10:16 +0100 |
---|---|---|
committer | Petr Mrázek <peterix@gmail.com> | 2016-11-03 01:11:57 +0100 |
commit | f0b71f989ea798495ad80d1f059ae0a28514f9a2 (patch) | |
tree | 8551131b5ce3ccaa3c422f6635aefdbf6ca149ff /api/logic/launch | |
parent | ac66af6c13604a4eb2d36cc82417aa6753b84afe (diff) | |
download | MultiMC-f0b71f989ea798495ad80d1f059ae0a28514f9a2.tar MultiMC-f0b71f989ea798495ad80d1f059ae0a28514f9a2.tar.gz MultiMC-f0b71f989ea798495ad80d1f059ae0a28514f9a2.tar.lz MultiMC-f0b71f989ea798495ad80d1f059ae0a28514f9a2.tar.xz MultiMC-f0b71f989ea798495ad80d1f059ae0a28514f9a2.zip |
NOISSUE use LoggedProcess to work around issues with QProcess on macOS
Diffstat (limited to 'api/logic/launch')
-rw-r--r-- | api/logic/launch/LoggedProcess.cpp | 176 | ||||
-rw-r--r-- | api/logic/launch/LoggedProcess.h | 79 | ||||
-rw-r--r-- | api/logic/launch/MessageLevel.cpp | 36 | ||||
-rw-r--r-- | api/logic/launch/MessageLevel.h | 28 | ||||
-rw-r--r-- | api/logic/launch/steps/PostLaunchCommand.h | 2 | ||||
-rw-r--r-- | api/logic/launch/steps/PreLaunchCommand.h | 4 | ||||
-rw-r--r-- | api/logic/launch/steps/TextPrint.h | 2 | ||||
-rw-r--r-- | api/logic/launch/steps/Update.h | 2 |
8 files changed, 5 insertions, 324 deletions
diff --git a/api/logic/launch/LoggedProcess.cpp b/api/logic/launch/LoggedProcess.cpp deleted file mode 100644 index f89b4acc..00000000 --- a/api/logic/launch/LoggedProcess.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#include "LoggedProcess.h" -#include "MessageLevel.h" -#include <QDebug> - -LoggedProcess::LoggedProcess(QObject *parent) : QProcess(parent) -{ - // QProcess has a strange interface... let's map a lot of those into a few. - connect(this, &QProcess::readyReadStandardOutput, this, &LoggedProcess::on_stdOut); - connect(this, &QProcess::readyReadStandardError, this, &LoggedProcess::on_stdErr); - connect(this, SIGNAL(finished(int,QProcess::ExitStatus)), SLOT(on_exit(int,QProcess::ExitStatus))); - connect(this, SIGNAL(error(QProcess::ProcessError)), this, SLOT(on_error(QProcess::ProcessError))); - connect(this, &QProcess::stateChanged, this, &LoggedProcess::on_stateChange); -} - -LoggedProcess::~LoggedProcess() -{ - if(m_is_detachable) - { - setProcessState(QProcess::NotRunning); - } -} - -QStringList reprocess(const QByteArray & data, QString & leftover) -{ - QString str = leftover + QString::fromLocal8Bit(data); - - str.remove('\r'); - QStringList lines = str.split("\n"); - leftover = lines.takeLast(); - return lines; -} - -void LoggedProcess::on_stdErr() -{ - auto lines = reprocess(readAllStandardError(), m_err_leftover); - emit log(lines, MessageLevel::StdErr); -} - -void LoggedProcess::on_stdOut() -{ - auto lines = reprocess(readAllStandardOutput(), m_out_leftover); - emit log(lines, MessageLevel::StdOut); -} - -void LoggedProcess::on_exit(int exit_code, QProcess::ExitStatus status) -{ - // save the exit code - m_exit_code = exit_code; - - // Flush console window - if (!m_err_leftover.isEmpty()) - { - emit log({m_err_leftover}, MessageLevel::StdErr); - m_err_leftover.clear(); - } - if (!m_out_leftover.isEmpty()) - { - emit log({m_err_leftover}, MessageLevel::StdOut); - m_out_leftover.clear(); - } - - // based on state, send signals - if (!m_is_aborting) - { - if (status == QProcess::NormalExit) - { - //: Message displayed on instance exit - emit log({tr("Process exited with code %1.").arg(exit_code)}, MessageLevel::MultiMC); - changeState(LoggedProcess::Finished); - } - else - { - //: Message displayed on instance crashed - if(exit_code == -1) - emit log({tr("Process crashed.")}, MessageLevel::MultiMC); - else - emit log({tr("Process crashed with exitcode %1.").arg(exit_code)}, MessageLevel::MultiMC); - changeState(LoggedProcess::Crashed); - } - } - else - { - //: Message displayed after the instance exits due to kill request - emit log({tr("Process was killed by user.")}, MessageLevel::Error); - changeState(LoggedProcess::Aborted); - } -} - -void LoggedProcess::on_error(QProcess::ProcessError error) -{ - switch(error) - { - case QProcess::FailedToStart: - { - emit log({tr("The process failed to start.")}, MessageLevel::Fatal); - changeState(LoggedProcess::FailedToStart); - break; - } - // we'll just ignore those... never needed them - case QProcess::Crashed: - case QProcess::ReadError: - case QProcess::Timedout: - case QProcess::UnknownError: - case QProcess::WriteError: - break; - } -} - -void LoggedProcess::kill() -{ - m_is_aborting = true; - QProcess::kill(); -} - -int LoggedProcess::exitCode() const -{ - return m_exit_code; -} - -void LoggedProcess::changeState(LoggedProcess::State state) -{ - if(state == m_state) - return; - m_state = state; - emit stateChanged(m_state); -} - -LoggedProcess::State LoggedProcess::state() const -{ - return m_state; -} - -void LoggedProcess::on_stateChange(QProcess::ProcessState state) -{ - switch(state) - { - case QProcess::NotRunning: - break; // let's not - there are too many that handle this already. - case QProcess::Starting: - { - if(m_state != LoggedProcess::NotRunning) - { - qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Starting; - } - changeState(LoggedProcess::Starting); - return; - } - case QProcess::Running: - { - if(m_state != LoggedProcess::Starting) - { - qWarning() << "Wrong state change for process from state" << m_state << "to" << (int) LoggedProcess::Running; - } - changeState(LoggedProcess::Running); - return; - } - } -} - -#if defined Q_OS_WIN32 -#include <windows.h> -#endif - -qint64 LoggedProcess::processId() const -{ -#ifdef Q_OS_WIN - return pid() ? pid()->dwProcessId : 0; -#else - return pid(); -#endif -} - -void LoggedProcess::setDetachable(bool detachable) -{ - m_is_detachable = detachable; -} diff --git a/api/logic/launch/LoggedProcess.h b/api/logic/launch/LoggedProcess.h deleted file mode 100644 index c4e5c52c..00000000 --- a/api/logic/launch/LoggedProcess.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Copyright 2013-2015 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include <QProcess> -#include "MessageLevel.h" - -/* - * This is a basic process. - * It has line-based logging support and hides some of the nasty bits. - */ -class LoggedProcess : public QProcess -{ -Q_OBJECT -public: - enum State - { - NotRunning, - Starting, - FailedToStart, - Running, - Finished, - Crashed, - Aborted - }; - -public: - explicit LoggedProcess(QObject* parent = 0); - virtual ~LoggedProcess(); - - State state() const; - int exitCode() const; - qint64 processId() const; - - void setDetachable(bool detachable); - -signals: - void log(QStringList lines, MessageLevel::Enum level); - void stateChanged(LoggedProcess::State state); - -public slots: - /** - * @brief kill the process - equivalent to kill -9 - */ - void kill(); - - -private slots: - void on_stdErr(); - void on_stdOut(); - void on_exit(int exit_code, QProcess::ExitStatus status); - void on_error(QProcess::ProcessError error); - void on_stateChange(QProcess::ProcessState); - -private: - void changeState(LoggedProcess::State state); - -private: - QString m_err_leftover; - QString m_out_leftover; - bool m_killed = false; - State m_state = NotRunning; - int m_exit_code = 0; - bool m_is_aborting = false; - bool m_is_detachable = false; -}; diff --git a/api/logic/launch/MessageLevel.cpp b/api/logic/launch/MessageLevel.cpp deleted file mode 100644 index a5191290..00000000 --- a/api/logic/launch/MessageLevel.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "MessageLevel.h" - -MessageLevel::Enum MessageLevel::getLevel(const QString& levelName) -{ - if (levelName == "MultiMC") - return MessageLevel::MultiMC; - else if (levelName == "Debug") - return MessageLevel::Debug; - else if (levelName == "Info") - return MessageLevel::Info; - else if (levelName == "Message") - return MessageLevel::Message; - else if (levelName == "Warning") - return MessageLevel::Warning; - else if (levelName == "Error") - return MessageLevel::Error; - else if (levelName == "Fatal") - return MessageLevel::Fatal; - // Skip PrePost, it's not exposed to !![]! - // Also skip StdErr and StdOut - else - return MessageLevel::Unknown; -} - -MessageLevel::Enum MessageLevel::fromLine(QString &line) -{ - // Level prefix - int endmark = line.indexOf("]!"); - if (line.startsWith("!![") && endmark != -1) - { - auto level = MessageLevel::getLevel(line.left(endmark).mid(3)); - line = line.mid(endmark + 2); - return level; - } - return MessageLevel::Unknown; -} diff --git a/api/logic/launch/MessageLevel.h b/api/logic/launch/MessageLevel.h deleted file mode 100644 index 0128148d..00000000 --- a/api/logic/launch/MessageLevel.h +++ /dev/null @@ -1,28 +0,0 @@ -#pragma once - -#include <QString> - -/** - * @brief the MessageLevel Enum - * defines what level a log message is - */ -namespace MessageLevel -{ -enum Enum -{ - Unknown, /**< No idea what this is or where it came from */ - StdOut, /**< Undetermined stderr messages */ - StdErr, /**< Undetermined stdout messages */ - MultiMC, /**< MultiMC Messages */ - Debug, /**< Debug Messages */ - Info, /**< Info Messages */ - Message, /**< Standard Messages */ - Warning, /**< Warnings */ - Error, /**< Errors */ - Fatal, /**< Fatal Errors */ -}; -MessageLevel::Enum getLevel(const QString &levelName); - -/* Get message level from a line. Line is modified if it was successful. */ -MessageLevel::Enum fromLine(QString &line); -} diff --git a/api/logic/launch/steps/PostLaunchCommand.h b/api/logic/launch/steps/PostLaunchCommand.h index 4d5b0a52..2b68ee86 100644 --- a/api/logic/launch/steps/PostLaunchCommand.h +++ b/api/logic/launch/steps/PostLaunchCommand.h @@ -16,7 +16,7 @@ #pragma once #include <launch/LaunchStep.h> -#include <launch/LoggedProcess.h> +#include <LoggedProcess.h> class PostLaunchCommand: public LaunchStep { diff --git a/api/logic/launch/steps/PreLaunchCommand.h b/api/logic/launch/steps/PreLaunchCommand.h index 077bdfca..eb7bc0b6 100644 --- a/api/logic/launch/steps/PreLaunchCommand.h +++ b/api/logic/launch/steps/PreLaunchCommand.h @@ -15,8 +15,8 @@ #pragma once -#include <launch/LaunchStep.h> -#include <launch/LoggedProcess.h> +#include "launch/LaunchStep.h" +#include "LoggedProcess.h" class PreLaunchCommand: public LaunchStep { diff --git a/api/logic/launch/steps/TextPrint.h b/api/logic/launch/steps/TextPrint.h index fdd9014a..5b82aff8 100644 --- a/api/logic/launch/steps/TextPrint.h +++ b/api/logic/launch/steps/TextPrint.h @@ -16,7 +16,7 @@ #pragma once #include <launch/LaunchStep.h> -#include <launch/LoggedProcess.h> +#include <LoggedProcess.h> #include <java/JavaChecker.h> #include "multimc_logic_export.h" diff --git a/api/logic/launch/steps/Update.h b/api/logic/launch/steps/Update.h index 1739de47..ad7cfa69 100644 --- a/api/logic/launch/steps/Update.h +++ b/api/logic/launch/steps/Update.h @@ -17,7 +17,7 @@ #include <launch/LaunchStep.h> #include <QObjectPtr.h> -#include <launch/LoggedProcess.h> +#include <LoggedProcess.h> #include <java/JavaChecker.h> // FIXME: stupid. should be defined by the instance type? or even completely abstracted away... |