diff --git a/sys/ExternalProcess.cpp b/sys/ExternalProcess.cpp index 03aaaf4..de6b35a 100644 --- a/sys/ExternalProcess.cpp +++ b/sys/ExternalProcess.cpp @@ -85,6 +85,19 @@ namespace NekoRay::sys { connect(this, &QProcess::readyReadStandardOutput, this, [&]() { auto log = readAllStandardOutput(); + if (!NekoRay::dataStore->core_running) { + if (log.contains("grpc server listening")) { + // The core really started + NekoRay::dataStore->core_running = true; + if (start_profile_when_core_is_up >= 0) { + MW_dialog_message("ExternalProcess", "CoreStarted," + Int2String(start_profile_when_core_is_up)); + start_profile_when_core_is_up = -1; + } + } else if (log.contains("failed to serve")) { + // The core failed to start + QProcess::kill(); + } + } if (logCounter.fetchAndAddRelaxed(log.count("\n")) > NekoRay::dataStore->max_log_line) return; MW_show_log(log); }); @@ -105,10 +118,13 @@ namespace NekoRay::sys { } }); connect(this, &QProcess::stateChanged, this, [&](QProcess::ProcessState state) { - NekoRay::dataStore->core_running = state == QProcess::Running; + if (state == QProcess::NotRunning) { + NekoRay::dataStore->core_running = false; + } if (!dataStore->prepare_exit && state == QProcess::NotRunning) { if (failed_to_start) return; // no retry + if (restarting) return; MW_dialog_message("ExternalProcess", "CoreCrashed"); @@ -124,18 +140,9 @@ namespace NekoRay::sys { } // Restart - restart_id = NekoRay::dataStore->started_id; + start_profile_when_core_is_up = NekoRay::dataStore->started_id; MW_show_log("[Error] " + QObject::tr("Core exited, restarting.")); - setTimeout([=] { Restart(); }, this, 1000); - } else if (state == QProcess::Running && restart_id >= 0) { - // Restart profile - setTimeout( - [=] { - MW_dialog_message("ExternalProcess", "CoreRestarted," + Int2String(restart_id)); - restart_id = -1; - }, - this, 1000); } }); } @@ -156,9 +163,12 @@ namespace NekoRay::sys { } void CoreProcess::Restart() { - Kill(); + restarting = true; + QProcess::kill(); + QProcess::waitForFinished(500); ExternalProcess::started = false; Start(); + restarting = false; } } // namespace NekoRay::sys diff --git a/sys/ExternalProcess.hpp b/sys/ExternalProcess.hpp index 440fd4a..f7c2886 100644 --- a/sys/ExternalProcess.hpp +++ b/sys/ExternalProcess.hpp @@ -35,10 +35,12 @@ namespace NekoRay::sys { void Restart(); + int start_profile_when_core_is_up = -1; + private: bool show_stderr = false; bool failed_to_start = false; - int restart_id = -1; + bool restarting = false; }; // 手动管理 diff --git a/ui/mainwindow.cpp b/ui/mainwindow.cpp index 4e34fd2..429a95b 100644 --- a/ui/mainwindow.cpp +++ b/ui/mainwindow.cpp @@ -410,12 +410,17 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi runOnUiThread( [=] { core_process = new NekoRay::sys::CoreProcess(core_path, args); + // Remember last started + if (NekoRay::dataStore->remember_enable && NekoRay::dataStore->remember_id >= 0) { + core_process->start_profile_when_core_is_up = NekoRay::dataStore->remember_id; + } + // Setup core_process->Start(); setup_grpc(); }, DS_cores); - // Start last + // Remember system proxy if (NekoRay::dataStore->remember_enable) { if (NekoRay::dataStore->remember_spmode.contains("system_proxy")) { neko_set_spmode_system_proxy(true, false); @@ -423,9 +428,6 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi if (NekoRay::dataStore->remember_spmode.contains("vpn")) { neko_set_spmode_vpn(true, false); } - if (NekoRay::dataStore->remember_id >= 0) { - runOnUiThread([=] { neko_start(NekoRay::dataStore->remember_id); }); - } } connect(qApp, &QGuiApplication::commitDataRequest, this, &MainWindow::on_commitDataRequest); @@ -578,7 +580,7 @@ void MainWindow::dialog_message_impl(const QString &sender, const QString &info) neko_stop(); } else if (info == "CoreCrashed") { neko_stop(true); - } else if (info.startsWith("CoreRestarted")) { + } else if (info.startsWith("CoreStarted")) { neko_start(info.split(",")[1].toInt()); } } diff --git a/ui/mainwindow_grpc.cpp b/ui/mainwindow_grpc.cpp index b46533f..93cd076 100644 --- a/ui/mainwindow_grpc.cpp +++ b/ui/mainwindow_grpc.cpp @@ -230,15 +230,6 @@ void MainWindow::neko_start(int _id) { } auto neko_start_stage2 = [=] { - if (!NekoRay::dataStore->core_running) { - runOnUiThread( - [=] { - core_process->Restart(); - }, - DS_cores); - QThread::sleep(1); - } - #ifndef NKR_NO_GRPC libcore::LoadConfigReq req; req.set_core_config(QJsonObject2QString(result->coreConfig, true).toStdString()); @@ -285,6 +276,25 @@ void MainWindow::neko_start(int _id) { MessageBoxWarning(software_name, "Another profile is starting..."); return; } + if (!mu_stopping.tryLock()) { + MessageBoxWarning(software_name, "Another profile is stopping..."); + mu_stopping.unlock(); + return; + } + mu_stopping.unlock(); + + // check core state + if (!NekoRay::dataStore->core_running) { + runOnUiThread( + [=] { + show_log_impl("Try to start the config, but the core has not listened to the grpc port, so restart it..."); + core_process->start_profile_when_core_is_up = ent->id; + core_process->Restart(); + }, + DS_cores); + mu_starting.unlock(); + return; // let CoreProcess call neko_start when core is up + } // timeout message auto restartMsgbox = new QMessageBox(QMessageBox::Question, software_name, tr("If there is no response for a long time, it is recommended to restart the software."),