fix: core log thread

This commit is contained in:
arm64v8a
2023-05-19 14:15:31 +09:00
parent 7471f3354f
commit ec25e0ed00
12 changed files with 99 additions and 62 deletions

View File

@@ -15,8 +15,8 @@ namespace NekoRay {
QStringList getAutoBypassExternalProcessPaths(const QSharedPointer<BuildConfigResult> &result) { QStringList getAutoBypassExternalProcessPaths(const QSharedPointer<BuildConfigResult> &result) {
QStringList paths; QStringList paths;
for (const auto &ext: result->exts) { for (const auto &extR: result->extRs) {
auto path = ext.first.program; auto path = extR->program;
if (path.trimmed().isEmpty()) continue; if (path.trimmed().isEmpty()) continue;
paths << path.replace("\\", "/"); paths << path.replace("\\", "/");
} }
@@ -553,7 +553,7 @@ namespace NekoRay {
auto stream = GetStreamSettings(ent->bean.data()); auto stream = GetStreamSettings(ent->bean.data());
if (thisExternalStat > 0) { if (thisExternalStat > 0) {
const auto extR = ent->bean->BuildExternal(ext_mapping_port, ext_socks_port, thisExternalStat); auto extR = ent->bean->BuildExternal(ext_mapping_port, ext_socks_port, thisExternalStat);
if (extR.program.isEmpty()) { if (extR.program.isEmpty()) {
status->result->error = QObject::tr("Core not found: %1").arg(ent->bean->DisplayType()); status->result->error = QObject::tr("Core not found: %1").arg(ent->bean->DisplayType());
return {}; return {};
@@ -562,6 +562,8 @@ namespace NekoRay {
status->result->error = extR.error; status->result->error = extR.error;
return {}; return {};
} }
extR.tag = ent->bean->DisplayType();
status->result->extRs.emplace_back(std::make_shared<fmt::ExternalBuildResult>(extR));
// SOCKS OUTBOUND // SOCKS OUTBOUND
if (IS_NEKO_BOX) { if (IS_NEKO_BOX) {
@@ -579,14 +581,6 @@ namespace NekoRay {
settings["servers"] = servers; settings["servers"] = servers;
outbound["settings"] = settings; outbound["settings"] = settings;
} }
// EXTERNAL PROCESS
QSharedPointer<sys::ExternalProcess> extC(new sys::ExternalProcess());
extC->tag = ent->bean->DisplayType();
extC->program = extR.program;
extC->arguments = extR.arguments;
extC->env = extR.env;
status->result->exts.emplace_back(extR, extC);
} else { } else {
const auto coreR = IS_NEKO_BOX ? ent->bean->BuildCoreObjSingBox() : ent->bean->BuildCoreObjV2Ray(); const auto coreR = IS_NEKO_BOX ? ent->bean->BuildCoreObjSingBox() : ent->bean->BuildCoreObjV2Ray();
if (coreR.outbound.isEmpty()) { if (coreR.outbound.isEmpty()) {

View File

@@ -13,7 +13,7 @@ namespace NekoRay {
QSharedPointer<traffic::TrafficData> outboundStat; // main QSharedPointer<traffic::TrafficData> outboundStat; // main
QStringList ignoreConnTag; QStringList ignoreConnTag;
std::list<std::pair<fmt::ExternalBuildResult, QSharedPointer<sys::ExternalProcess>>> exts; // extR to extC std::list<std::shared_ptr<NekoRay::fmt::ExternalBuildResult>> extRs;
}; };
class BuildConfigStatus { class BuildConfigStatus {

View File

@@ -17,6 +17,9 @@ namespace NekoRay::fmt {
QString program; QString program;
QStringList env; QStringList env;
QStringList arguments; QStringList arguments;
//
QString tag;
//
QString error; QString error;
QString config_export; QString config_export;
}; };

View File

@@ -210,7 +210,12 @@ int MessageBoxInfo(const QString &title, const QString &text) {
void runOnUiThread(const std::function<void()> &callback, QObject *parent) { void runOnUiThread(const std::function<void()> &callback, QObject *parent) {
// any thread // any thread
auto *timer = new QTimer(); auto *timer = new QTimer();
auto thread = dynamic_cast<QThread *>(parent);
if (thread == nullptr) {
timer->moveToThread(parent == nullptr ? mainwindow->thread() : parent->thread()); timer->moveToThread(parent == nullptr ? mainwindow->thread() : parent->thread());
} else {
timer->moveToThread(thread);
}
timer->setSingleShot(true); timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, [=]() { QObject::connect(timer, &QTimer::timeout, [=]() {
// main thread // main thread

View File

@@ -23,6 +23,11 @@ inline std::function<void(QString, QString)> MW_show_log_ext;
inline std::function<void(QString)> MW_show_log_ext_vt100; inline std::function<void(QString)> MW_show_log_ext_vt100;
inline std::function<void(QString, QString)> MW_dialog_message; inline std::function<void(QString, QString)> MW_dialog_message;
// Dispatchers
class QThread;
inline QThread *DS_cores;
// String // String
#define FIRST_OR_SECOND(a, b) a.isEmpty() ? b : a #define FIRST_OR_SECOND(a, b) a.isEmpty() ? b : a

View File

@@ -7,6 +7,7 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QLocalSocket> #include <QLocalSocket>
#include <QLocalServer> #include <QLocalServer>
#include <QThread>
#include "3rdparty/RunGuard.hpp" #include "3rdparty/RunGuard.hpp"
#include "main/NekoRay.hpp" #include "main/NekoRay.hpp"
@@ -121,6 +122,10 @@ int main(int argc, char* argv[]) {
delete preQApp; delete preQApp;
QApplication a(argc, argv); QApplication a(argc, argv);
// dispatchers
DS_cores = new QThread;
DS_cores->start();
// RunGuard // RunGuard
RunGuard guard("nekoray" + wd.absolutePath()); RunGuard guard("nekoray" + wd.absolutePath());
quint64 guard_data_in = GetRandomUint64(); quint64 guard_data_in = GetRandomUint64();

View File

@@ -4,8 +4,10 @@
#include <QTimer> #include <QTimer>
#include <QDir> #include <QDir>
#include <QApplication> #include <QApplication>
#include <QThread>
namespace NekoRay::sys { namespace NekoRay::sys {
ExternalProcess::ExternalProcess() : QProcess() { ExternalProcess::ExternalProcess() : QProcess() {
// qDebug() << "[Debug] ExternalProcess()" << this << running_ext; // qDebug() << "[Debug] ExternalProcess()" << this << running_ext;
this->env = QProcessEnvironment::systemEnvironment().toStringList(); this->env = QProcessEnvironment::systemEnvironment().toStringList();
@@ -21,7 +23,9 @@ namespace NekoRay::sys {
if (managed) { if (managed) {
connect(this, &QProcess::readyReadStandardOutput, this, [&]() { connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
MW_show_log_ext_vt100(readAllStandardOutput().trimmed()); auto log = readAllStandardOutput();
if (logCounter.fetchAndAddRelaxed(log.count("\n")) > NekoRay::dataStore->max_log_line) return;
MW_show_log_ext_vt100(log);
}); });
connect(this, &QProcess::readyReadStandardError, this, [&]() { connect(this, &QProcess::readyReadStandardError, this, [&]() {
MW_show_log_ext_vt100(readAllStandardError().trimmed()); MW_show_log_ext_vt100(readAllStandardError().trimmed());
@@ -36,7 +40,7 @@ namespace NekoRay::sys {
connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) { connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) {
if (state == QProcess::NotRunning) { if (state == QProcess::NotRunning) {
if (killed) { // 用户命令退出 if (killed) { // 用户命令退出
MW_show_log_ext(tag, "Stopped"); MW_show_log_ext(tag, "External core stopped");
} else if (!crashed) { // 异常退出 } else if (!crashed) { // 异常退出
crashed = true; crashed = true;
MW_show_log_ext(tag, "[Error] Program exited accidentally: " + errorString()); MW_show_log_ext(tag, "[Error] Program exited accidentally: " + errorString());
@@ -45,7 +49,7 @@ namespace NekoRay::sys {
} }
} }
}); });
MW_show_log_ext(tag, "[Starting] " + env.join(" ") + " " + program + " " + arguments.join(" ")); MW_show_log_ext(tag, "External core starting: " + env.join(" ") + " " + program + " " + arguments.join(" "));
} }
QProcess::setEnvironment(env); QProcess::setEnvironment(env);
@@ -76,7 +80,9 @@ namespace NekoRay::sys {
ExternalProcess::arguments = args; ExternalProcess::arguments = args;
connect(this, &QProcess::readyReadStandardOutput, this, [&]() { connect(this, &QProcess::readyReadStandardOutput, this, [&]() {
MW_show_log(readAllStandardOutput().trimmed()); auto log = readAllStandardOutput();
if (logCounter.fetchAndAddRelaxed(log.count("\n")) > NekoRay::dataStore->max_log_line) return;
MW_show_log(log);
}); });
connect(this, &QProcess::readyReadStandardError, this, [&]() { connect(this, &QProcess::readyReadStandardError, this, [&]() {
auto log = readAllStandardError().trimmed(); auto log = readAllStandardError().trimmed();

View File

@@ -40,5 +40,7 @@ namespace NekoRay::sys {
}; };
// 手动管理 // 手动管理
inline QList<QSharedPointer<ExternalProcess>> running_ext; inline std::list<QSharedPointer<ExternalProcess>> running_ext;
inline QAtomicInt logCounter;
} // namespace NekoRay::sys } // namespace NekoRay::sys

View File

@@ -115,15 +115,14 @@ void EditCustom::onStart(QSharedPointer<NekoRay::ProxyEntity> _ent) {
MessageBoxInfo(software_name, result->error); MessageBoxInfo(software_name, result->error);
return; return;
} }
for (const auto &ext: result->exts) { for (const auto &extR: result->extRs) {
auto extR = ext.first; auto command = QStringList{extR->program};
auto command = QStringList{extR.program}; command += extR->arguments;
command += extR.arguments;
auto btn = QMessageBox::information(this, tr("Preview config"), auto btn = QMessageBox::information(this, tr("Preview config"),
QString("Command: %1\n\n%2").arg(QStringList2Command(command), extR.config_export), QString("Command: %1\n\n%2").arg(QStringList2Command(command), extR->config_export),
"OK", "Copy", "", 0, 0); "OK", "Copy", "", 0, 0);
if (btn == 1) { if (btn == 1) {
QApplication::clipboard()->setText(extR.config_export); QApplication::clipboard()->setText(extR->config_export);
} }
} }
}); });

View File

@@ -47,7 +47,6 @@
#include <QElapsedTimer> #include <QElapsedTimer>
QElapsedTimer coreRestartTimer; QElapsedTimer coreRestartTimer;
// QAtomicInt logCounter;
void UI_InitMainWindow() { void UI_InitMainWindow() {
mainwindow = new MainWindow; mainwindow = new MainWindow;
@@ -150,11 +149,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
MW_show_log_ext_vt100 = [=](const QString &log) { MW_show_log_ext_vt100 = [=](const QString &log) {
runOnUiThread([=] { show_log_impl(cleanVT100String(log)); }); runOnUiThread([=] { show_log_impl(cleanVT100String(log)); });
}; };
//
// auto logCounterTimer = new QTimer(this);
// connect(logCounterTimer, &QTimer::timeout, this, [&] { logCounter.fetchAndStoreRelaxed(0); });
// logCounterTimer->setInterval(1000);
// logCounterTimer->start();
// table UI // table UI
ui->proxyListTable->callback_save_order = [=] { ui->proxyListTable->callback_save_order = [=] {
@@ -416,10 +410,13 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
if (NekoRay::dataStore->flag_debug) args.push_back("-debug"); if (NekoRay::dataStore->flag_debug) args.push_back("-debug");
// Start core // Start core
runOnUiThread(
[=] {
core_process = new NekoRay::sys::CoreProcess(core_path, args); core_process = new NekoRay::sys::CoreProcess(core_path, args);
core_process->Start(); core_process->Start();
setup_grpc(); setup_grpc();
},
DS_cores);
// Start last // Start last
if (NekoRay::dataStore->remember_enable) { if (NekoRay::dataStore->remember_enable) {
@@ -436,6 +433,14 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
connect(qApp, &QGuiApplication::commitDataRequest, this, &MainWindow::on_commitDataRequest); connect(qApp, &QGuiApplication::commitDataRequest, this, &MainWindow::on_commitDataRequest);
auto t = new QTimer;
connect(t, &QTimer::timeout, this, [=]() { refresh_status(); });
t->start(2000);
t = new QTimer;
connect(t, &QTimer::timeout, this, [&] { NekoRay::sys::logCounter.fetchAndStoreRelaxed(0); });
t->start(1000);
if (!NekoRay::dataStore->flag_tray) show(); if (!NekoRay::dataStore->flag_tray) show();
} }
@@ -1497,7 +1502,6 @@ void MainWindow::show_log_impl(const QString &log) {
if (showThisLine) newLines << line; if (showThisLine) newLines << line;
} }
if (newLines.isEmpty()) return; if (newLines.isEmpty()) return;
// if (logCounter.fetchAndAddRelaxed(newLines.count()) > NekoRay::dataStore->max_log_line) return;
FastAppendTextDocument(newLines.join("\n"), qvLogDocument); FastAppendTextDocument(newLines.join("\n"), qvLogDocument);
// qvLogDocument->setPlainText(qvLogDocument->toPlainText() + log); // qvLogDocument->setPlainText(qvLogDocument->toPlainText() + log);

View File

@@ -185,7 +185,7 @@ private:
// grpc and ... // grpc and ...
void setup_grpc(); static void setup_grpc();
void speedtest_current_group(int mode); void speedtest_current_group(int mode);

View File

@@ -14,6 +14,26 @@
#include <QDesktopServices> #include <QDesktopServices>
#include <QMessageBox> #include <QMessageBox>
// ext core
std::list<QSharedPointer<NekoRay::sys::ExternalProcess>> CreateExtCFromExtR(const std::list<std::shared_ptr<NekoRay::fmt::ExternalBuildResult>> &extRs, bool start) {
// plz run and start in same thread
std::list<QSharedPointer<NekoRay::sys::ExternalProcess>> l;
for (const auto &extR: extRs) {
QSharedPointer<NekoRay::sys::ExternalProcess> extC(new NekoRay::sys::ExternalProcess());
extC->tag = extR->tag;
extC->program = extR->program;
extC->arguments = extR->arguments;
extC->env = extR->env;
l.emplace_back(extC);
//
if (start) extC->Start();
}
return l;
}
// grpc
#ifndef NKR_NO_GRPC #ifndef NKR_NO_GRPC
using namespace NekoRay::rpc; using namespace NekoRay::rpc;
#endif #endif
@@ -89,16 +109,13 @@ void MainWindow::speedtest_current_group(int mode) {
req.set_url(NekoRay::dataStore->test_url.toStdString()); req.set_url(NekoRay::dataStore->test_url.toStdString());
// //
std::list<std::pair<NekoRay::fmt::ExternalBuildResult, QSharedPointer<NekoRay::sys::ExternalProcess>>> exts; std::list<QSharedPointer<NekoRay::sys::ExternalProcess>> extCs;
if (mode == libcore::TestMode::UrlTest || mode == libcore::FullTest) { if (mode == libcore::TestMode::UrlTest || mode == libcore::FullTest) {
auto c = NekoRay::BuildConfig(profile, true, false); auto c = NekoRay::BuildConfig(profile, true, false);
// TODO refactor external test // TODO refactor external test
if (!c->exts.empty()) { if (!c->extRs.empty()) {
exts = c->exts; extCs = CreateExtCFromExtR(c->extRs, true);
for (const auto &ext: exts) {
ext.second->Start();
}
QThread::msleep(500); QThread::msleep(500);
} }
// //
@@ -117,8 +134,8 @@ void MainWindow::speedtest_current_group(int mode) {
bool rpcOK; bool rpcOK;
auto result = defaultClient->Test(&rpcOK, req); auto result = defaultClient->Test(&rpcOK, req);
for (const auto &ext: exts) { for (const auto &extC: extCs) {
ext.second->Kill(); extC->Kill();
} }
if (!rpcOK) return; if (!rpcOK) return;
@@ -178,16 +195,6 @@ void MainWindow::speedtest_current() {
} else if (latency > 0) { } else if (latency > 0) {
ui->label_running->setText(tr("Test Result") + ": " + QString("%1 ms").arg(latency)); ui->label_running->setText(tr("Test Result") + ": " + QString("%1 ms").arg(latency));
} }
//
auto t = new QTimer(this);
connect(t, &QTimer::timeout, this, [=] {
last_test_time = QTime();
refresh_status();
t->deleteLater();
});
t->setInterval(1000);
t->setSingleShot(true);
t->start();
}); });
}); });
#endif #endif
@@ -245,10 +252,12 @@ void MainWindow::neko_start(int _id) {
NekoRay::traffic::trafficLooper->loop_enabled = true; NekoRay::traffic::trafficLooper->loop_enabled = true;
#endif #endif
for (const auto &ext: result->exts) { runOnUiThread(
NekoRay::sys::running_ext.push_back(ext.second); [=] {
ext.second->Start(); auto extCs = CreateExtCFromExtR(result->extRs, true);
} NekoRay::sys::running_ext.splice(NekoRay::sys::running_ext.end(), extCs);
},
DS_cores);
NekoRay::dataStore->UpdateStartedId(ent->id); NekoRay::dataStore->UpdateStartedId(ent->id);
running = ent; running = ent;
@@ -301,10 +310,15 @@ void MainWindow::neko_stop(bool crash, bool sem) {
} }
auto neko_stop_stage2 = [=] { auto neko_stop_stage2 = [=] {
while (!NekoRay::sys::running_ext.isEmpty()) { runOnUiThread(
auto extC = NekoRay::sys::running_ext.takeFirst(); [=] {
while (!NekoRay::sys::running_ext.empty()) {
auto extC = NekoRay::sys::running_ext.front();
extC->Kill(); extC->Kill();
NekoRay::sys::running_ext.pop_front();
} }
},
DS_cores);
#ifndef NKR_NO_GRPC #ifndef NKR_NO_GRPC
NekoRay::traffic::trafficLooper->loop_enabled = false; NekoRay::traffic::trafficLooper->loop_enabled = false;