mirror of
https://github.com/MatsuriDayo/nekoray.git
synced 2025-12-17 20:44:38 +03:00
refactor core_process (1)
This commit is contained in:
@@ -399,8 +399,11 @@ namespace NekoRay {
|
||||
outbound["settings"] = settings;
|
||||
|
||||
// EXTERNAL PROCESS
|
||||
auto extC = new sys::ExternalProcess(ent->bean->DisplayType(),
|
||||
extR.program, extR.arguments, extR.env);
|
||||
auto extC = new sys::ExternalProcess();
|
||||
extC->tag = ent->bean->DisplayType();
|
||||
extC->program = extR.program;
|
||||
extC->arguments = extR.arguments;
|
||||
extC->env = extR.env;
|
||||
status->result->ext += extC;
|
||||
} else {
|
||||
coreR = ent->bean->BuildCoreObj();
|
||||
|
||||
@@ -41,6 +41,8 @@ namespace NekoRay {
|
||||
QString core_token;
|
||||
int core_port = 19810;
|
||||
int started_id = -1919;
|
||||
bool core_running = false;
|
||||
bool core_prepare_exit = false;
|
||||
|
||||
Routing *routing = new Routing;
|
||||
int imported_count = 0;
|
||||
|
||||
@@ -23,8 +23,6 @@ namespace QtGrpc {
|
||||
const char *GrpcStatusMessage = "grpc-message";
|
||||
const int GrpcMessageSizeHeaderSize = 5;
|
||||
|
||||
bool core_crashed = false;
|
||||
|
||||
class Http2GrpcChannelPrivate : public QObject {
|
||||
private:
|
||||
QString url_base;
|
||||
@@ -135,7 +133,7 @@ namespace QtGrpc {
|
||||
QNetworkReply::NetworkError Call(const QString &methodName,
|
||||
const google::protobuf::Message &req, google::protobuf::Message *rsp,
|
||||
int timeout_ms = 0) {
|
||||
if (core_crashed) return QNetworkReply::NetworkError(-1919);
|
||||
if (!NekoRay::dataStore->core_running) return QNetworkReply::NetworkError(-1919);
|
||||
|
||||
std::string reqStr;
|
||||
req.SerializeToString(&reqStr);
|
||||
|
||||
@@ -1,57 +1,46 @@
|
||||
#include "ExternalProcess.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
namespace NekoRay::sys {
|
||||
ExternalProcess::ExternalProcess(const QString &tag,
|
||||
const QString &program,
|
||||
const QStringList &arguments,
|
||||
const QStringList &env)
|
||||
: QProcess() {
|
||||
this->tag = tag;
|
||||
this->program = program;
|
||||
this->arguments = arguments;
|
||||
this->env = env;
|
||||
this->running_list = &running_ext;
|
||||
}
|
||||
ExternalProcess::ExternalProcess() : QProcess() {}
|
||||
|
||||
void ExternalProcess::Start() {
|
||||
if (started) return;
|
||||
started = true;
|
||||
*running_list += this;
|
||||
if (managed) running_ext.push_back(this);
|
||||
|
||||
if (show_log) {
|
||||
connect(this, &QProcess::readyReadStandardOutput, this,
|
||||
[&]() {
|
||||
connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
|
||||
showLog_ext_vt100(readAllStandardOutput().trimmed());
|
||||
});
|
||||
connect(this, &QProcess::readyReadStandardError, this,
|
||||
[&]() {
|
||||
connect(this, &QProcess::readyReadStandardError, this, [&]() {
|
||||
showLog_ext_vt100(readAllStandardError().trimmed());
|
||||
});
|
||||
}
|
||||
|
||||
connect(this, &QProcess::errorOccurred, this,
|
||||
[&](QProcess::ProcessError error) {
|
||||
if (managed) {
|
||||
connect(this, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) {
|
||||
if (!killed) {
|
||||
crashed = true;
|
||||
showLog_ext(tag, "[Error] Crashed:" + QProcess::errorString());
|
||||
showLog_ext(tag, "errorOccurred:" + errorString());
|
||||
dialog_message("ExternalProcess", "Crashed");
|
||||
}
|
||||
});
|
||||
connect(this, &QProcess::stateChanged, this,
|
||||
[&](QProcess::ProcessState state) {
|
||||
connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
|
||||
if (state == QProcess::NotRunning) {
|
||||
if (killed) {
|
||||
if (killed) { // 用户命令退出
|
||||
showLog_ext(tag, "Stopped");
|
||||
} else if (!crashed) {
|
||||
} else if (!crashed) { // 异常退出
|
||||
crashed = true;
|
||||
showLog_ext(tag, "[Error] Program exited accidentally: " + errorString());
|
||||
Kill();
|
||||
showLog_ext(tag, "[Error] Program exited accidentally");
|
||||
dialog_message("ExternalProcess", "Crashed");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
showLog_ext(tag, "[Starting] " + env.join(" ") + " " + program + " " + arguments.join(" "));
|
||||
}
|
||||
|
||||
QProcess::setEnvironment(env);
|
||||
QProcess::start(program, arguments);
|
||||
@@ -60,11 +49,71 @@ namespace NekoRay::sys {
|
||||
void ExternalProcess::Kill() {
|
||||
if (killed) return;
|
||||
killed = true;
|
||||
running_list->removeAll(this);
|
||||
if (managed) running_ext.removeAll(this);
|
||||
|
||||
if (!crashed) {
|
||||
QProcess::kill();
|
||||
QProcess::waitForFinished(500);
|
||||
}
|
||||
}
|
||||
|
||||
CoreProcess::CoreProcess(const QString &core_path, const QStringList &args) {
|
||||
ExternalProcess::managed = false;
|
||||
ExternalProcess::show_log = false;
|
||||
ExternalProcess::program = core_path;
|
||||
ExternalProcess::arguments = args;
|
||||
|
||||
connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
|
||||
showLog(readAllStandardOutput().trimmed());
|
||||
});
|
||||
connect(this, &QProcess::readyReadStandardError, this, [&]() {
|
||||
auto log = readAllStandardError().trimmed();
|
||||
if (show_stderr) {
|
||||
showLog(log);
|
||||
return;
|
||||
}
|
||||
if (log.contains("token is set")) {
|
||||
show_stderr = true;
|
||||
}
|
||||
});
|
||||
connect(this, &QProcess::errorOccurred, this, [&](QProcess::ProcessError error) {
|
||||
if (error == QProcess::ProcessError::FailedToStart) {
|
||||
failed_to_start = true;
|
||||
showLog("start nekoray_core errorOccurred: " + errorString() + "\n");
|
||||
}
|
||||
});
|
||||
connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
|
||||
NekoRay::dataStore->core_running = state == QProcess::Running;
|
||||
|
||||
if (!dataStore->core_prepare_exit && state == QProcess::NotRunning) {
|
||||
if (failed_to_start) return; // no retry
|
||||
|
||||
showLog("[Error] nekoray_core exited, restarting.\n");
|
||||
|
||||
// Restart
|
||||
auto t = new QTimer;
|
||||
connect(t, &QTimer::timeout, this, [=] {
|
||||
Kill();
|
||||
ExternalProcess::started = false;
|
||||
Start();
|
||||
t->deleteLater();
|
||||
});
|
||||
t->setSingleShot(true);
|
||||
t->setInterval(1000);
|
||||
t->start();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void CoreProcess::Start() {
|
||||
show_stderr = false;
|
||||
if (!dataStore->v2ray_asset_dir.isEmpty()) {
|
||||
setEnvironment(QStringList{
|
||||
"V2RAY_LOCATION_ASSET=" + dataStore->v2ray_asset_dir
|
||||
});
|
||||
}
|
||||
ExternalProcess::Start();
|
||||
write((dataStore->core_token + "\n").toUtf8());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,26 +12,34 @@ namespace NekoRay::sys {
|
||||
QStringList arguments;
|
||||
QStringList env;
|
||||
|
||||
bool managed = true; // running_ext & stateChanged
|
||||
bool show_log = true;
|
||||
QList<ExternalProcess *> *running_list;
|
||||
|
||||
ExternalProcess(const QString &tag,
|
||||
const QString &program,
|
||||
const QStringList &arguments,
|
||||
const QStringList &env);
|
||||
ExternalProcess();
|
||||
|
||||
// start & kill is one time
|
||||
|
||||
void Start();
|
||||
virtual void Start();
|
||||
|
||||
void Kill();
|
||||
|
||||
private:
|
||||
protected:
|
||||
bool started = false;
|
||||
bool killed = false;
|
||||
bool crashed = false;
|
||||
};
|
||||
|
||||
class CoreProcess : public ExternalProcess {
|
||||
public:
|
||||
CoreProcess(const QString &core_path, const QStringList &args);
|
||||
|
||||
void Start() override;
|
||||
|
||||
private:
|
||||
bool show_stderr = false;
|
||||
bool failed_to_start = false;
|
||||
};
|
||||
|
||||
// start & kill change this list
|
||||
inline QList<ExternalProcess *> running_ext;
|
||||
}
|
||||
|
||||
@@ -52,10 +52,6 @@
|
||||
#include <QFileInfo>
|
||||
#include <QFileSystemWatcher>
|
||||
|
||||
namespace QtGrpc {
|
||||
extern bool core_crashed;
|
||||
}
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent), ui(new Ui::MainWindow) {
|
||||
mainwindow = this;
|
||||
@@ -343,21 +339,14 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
connect(ui->menu_full_test, &QAction::triggered, this, [=]() { speedtest_current_group(2); });
|
||||
refresh_status();
|
||||
|
||||
// Start Core
|
||||
// Prepare core
|
||||
NekoRay::dataStore->core_token = GetRandomString(32);
|
||||
NekoRay::dataStore->core_port = MkPort();
|
||||
if (NekoRay::dataStore->core_port <= 0) NekoRay::dataStore->core_port = 19810;
|
||||
|
||||
QString starting_info;
|
||||
auto core_path = NekoRay::dataStore->core_path;
|
||||
#ifdef Q_OS_WIN
|
||||
if (!core_path.endsWith(".exe")) core_path += ".exe";
|
||||
#endif
|
||||
if (NekoRay::dataStore->flag_use_appdata) {
|
||||
core_path = QApplication::applicationDirPath() + "/nekoray_core";
|
||||
} else if (!QFile(core_path).exists()) {
|
||||
starting_info = "(not found)";
|
||||
core_path = "";
|
||||
}
|
||||
|
||||
QStringList args;
|
||||
@@ -368,40 +357,9 @@ MainWindow::MainWindow(QWidget *parent)
|
||||
args.push_back("-debug");
|
||||
#endif
|
||||
|
||||
showLog("Starting nekoray core " + starting_info + "\n");
|
||||
|
||||
if (!core_path.isEmpty()) {
|
||||
core_process = new QProcess;
|
||||
core_process_show_stderr = false;
|
||||
|
||||
connect(core_process, &QProcess::readyReadStandardOutput, this, [&]() {
|
||||
showLog(core_process->readAllStandardOutput().trimmed());
|
||||
});
|
||||
connect(core_process, &QProcess::readyReadStandardError, this, [&]() {
|
||||
auto log = core_process->readAllStandardError().trimmed();
|
||||
if (core_process_show_stderr) {
|
||||
showLog(log);
|
||||
return;
|
||||
}
|
||||
if (log.contains("token is set")) {
|
||||
core_process_show_stderr = true;
|
||||
}
|
||||
});
|
||||
connect(core_process, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
|
||||
if (!prepare_exit_core && state == QProcess::NotRunning) {
|
||||
QtGrpc::core_crashed = true;
|
||||
showLog("[Error] nekoray_core crashed, please restart the program.");
|
||||
}
|
||||
});
|
||||
|
||||
if (!NekoRay::dataStore->v2ray_asset_dir.isEmpty()) {
|
||||
core_process->setEnvironment(QStringList{
|
||||
"V2RAY_LOCATION_ASSET=" + NekoRay::dataStore->v2ray_asset_dir
|
||||
});
|
||||
}
|
||||
core_process->start(core_path, args);
|
||||
core_process->write((NekoRay::dataStore->core_token + "\n").toUtf8());
|
||||
}
|
||||
// Start core
|
||||
core_process = new NekoRay::sys::CoreProcess(core_path, args);
|
||||
core_process->Start();
|
||||
|
||||
setup_grpc();
|
||||
|
||||
@@ -563,7 +521,7 @@ void MainWindow::on_menu_exit_triggered() {
|
||||
//
|
||||
on_commitDataRequest();
|
||||
//
|
||||
prepare_exit_core = true;
|
||||
NekoRay::dataStore->core_prepare_exit = true;
|
||||
hide();
|
||||
ExitNekorayCore();
|
||||
//
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "main/GuiUtils.hpp"
|
||||
|
||||
class QFileSystemWatcher;
|
||||
namespace NekoRay::sys { class CoreProcess; }
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui {
|
||||
@@ -120,9 +121,7 @@ private:
|
||||
QShortcut *shortcut_ctrl_f = new QShortcut(QKeySequence("Ctrl+F"), this);
|
||||
QShortcut *shortcut_esc = new QShortcut(QKeySequence("Esc"), this);
|
||||
//
|
||||
QProcess *core_process;
|
||||
bool prepare_exit_core = false;
|
||||
bool core_process_show_stderr = false;
|
||||
NekoRay::sys::CoreProcess *core_process;
|
||||
qint64 vpn_pid = 0;
|
||||
QFileSystemWatcher *watcher = nullptr;
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user