From 7b4a542890b30e60eaf31e25af143b0674bcac8e Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Mon, 14 Aug 2023 15:42:07 +0400 Subject: [PATCH] Always wait for updater to exit on Linux --- Telegram/SourceFiles/_other/updater_linux.cpp | 135 +++++------------- .../platform/linux/launcher_linux.cpp | 65 ++++----- 2 files changed, 60 insertions(+), 140 deletions(-) diff --git a/Telegram/SourceFiles/_other/updater_linux.cpp b/Telegram/SourceFiles/_other/updater_linux.cpp index 40404c223..ca191e601 100644 --- a/Telegram/SourceFiles/_other/updater_linux.cpp +++ b/Telegram/SourceFiles/_other/updater_linux.cpp @@ -47,7 +47,6 @@ string updaterName; string workDir; string exeName; string exePath; -string argv0; FILE *_logFile = 0; void openLog() { @@ -357,40 +356,17 @@ string CurrentExecutablePath(int argc, char *argv[]) { } int main(int argc, char *argv[]) { - bool needupdate = true; - bool autostart = false; - bool debug = false; - bool tosettings = false; - bool startintray = false; - bool customWorkingDir = false; - - char *key = 0; - char *workdir = 0; for (int i = 1; i < argc; ++i) { - if (equal(argv[i], "-noupdate")) { - needupdate = false; - } else if (equal(argv[i], "-autostart")) { - autostart = true; - } else if (equal(argv[i], "-debug")) { - debug = _debug = true; - } else if (equal(argv[i], "-startintray")) { - startintray = true; - } else if (equal(argv[i], "-tosettings")) { - tosettings = true; - } else if (equal(argv[i], "-workdir_custom")) { - customWorkingDir = true; + if (equal(argv[i], "-debug")) { + _debug = true; } else if (equal(argv[i], "-writeprotected")) { writeprotected = true; - } else if (equal(argv[i], "-key") && ++i < argc) { - key = argv[i]; } else if (equal(argv[i], "-workpath") && ++i < argc) { - workDir = workdir = argv[i]; + workDir = argv[i]; } else if (equal(argv[i], "-exename") && ++i < argc) { exeName = argv[i]; } else if (equal(argv[i], "-exepath") && ++i < argc) { exePath = argv[i]; - } else if (equal(argv[i], "-argv0") && ++i < argc) { - argv0 = argv[i]; } } if (exeName.empty() || exeName.find('/') != string::npos) { @@ -402,8 +378,6 @@ int main(int argc, char *argv[]) { for (int i = 0; i < argc; ++i) { writeLog("Argument: '%s'", argv[i]); } - if (needupdate) writeLog("Need to update!"); - if (autostart) writeLog("From autostart!"); if (writeprotected) writeLog("Write Protected folder!"); updaterName = CurrentExecutablePath(argc, argv); @@ -421,42 +395,38 @@ int main(int argc, char *argv[]) { exePath = updaterDir; writeLog("Using updater binary dir.", exePath.c_str()); } - if (needupdate) { - if (workDir.empty()) { // old app launched, update prepared in tupdates/ready (not in tupdates/temp) - customWorkingDir = false; - - writeLog("No workdir, trying to figure it out"); - struct passwd *pw = getpwuid(getuid()); - if (pw && pw->pw_dir && strlen(pw->pw_dir)) { - string tryDir = pw->pw_dir + string("/.TelegramDesktop/"); - struct stat statbuf; - writeLog("Trying to use '%s' as workDir, getting stat() for tupdates/ready", tryDir.c_str()); - if (!stat((tryDir + "tupdates/ready").c_str(), &statbuf)) { - writeLog("Stat got"); - if (S_ISDIR(statbuf.st_mode)) { - writeLog("It is directory, using home work dir"); - workDir = tryDir; - } + if (workDir.empty()) { // old app launched, update prepared in tupdates/ready (not in tupdates/temp) + writeLog("No workdir, trying to figure it out"); + struct passwd *pw = getpwuid(getuid()); + if (pw && pw->pw_dir && strlen(pw->pw_dir)) { + string tryDir = pw->pw_dir + string("/.TelegramDesktop/"); + struct stat statbuf; + writeLog("Trying to use '%s' as workDir, getting stat() for tupdates/ready", tryDir.c_str()); + if (!stat((tryDir + "tupdates/ready").c_str(), &statbuf)) { + writeLog("Stat got"); + if (S_ISDIR(statbuf.st_mode)) { + writeLog("It is directory, using home work dir"); + workDir = tryDir; } } - if (workDir.empty()) { - workDir = exePath; - - struct stat statbuf; - writeLog("Trying to use current as workDir, getting stat() for tupdates/ready"); - if (!stat("tupdates/ready", &statbuf)) { - writeLog("Stat got"); - if (S_ISDIR(statbuf.st_mode)) { - writeLog("It is directory, using current dir"); - workDir = string(); - } - } - } - } else { - writeLog("Passed workpath is '%s'", workDir.c_str()); } - update(); + if (workDir.empty()) { + workDir = exePath; + + struct stat statbuf; + writeLog("Trying to use current as workDir, getting stat() for tupdates/ready"); + if (!stat("tupdates/ready", &statbuf)) { + writeLog("Stat got"); + if (S_ISDIR(statbuf.st_mode)) { + writeLog("It is directory, using current dir"); + workDir = string(); + } + } + } + } else { + writeLog("Passed workpath is '%s'", workDir.c_str()); } + update(); } else { writeLog("Error: bad exe name!"); } @@ -464,48 +434,7 @@ int main(int argc, char *argv[]) { writeLog("Error: short exe name!"); } - const auto fullBinaryPath = exePath + exeName; - - auto values = vector(); - const auto push = [&](string arg) { - // Force null-terminated .data() call result. - values.push_back(arg + char(0)); - }; - push(!argv0.empty() ? argv0 : fullBinaryPath); - push("-noupdate"); - if (autostart) push("-autostart"); - if (debug) push("-debug"); - if (startintray) push("-startintray"); - if (tosettings) push("-tosettings"); - if (key) { - push("-key"); - push(key); - } - if (customWorkingDir && workdir) { - push("-workdir"); - push(workdir); - } - - auto args = vector(); - for (auto &arg : values) { - args.push_back(arg.data()); - } - args.push_back(nullptr); - - // let the parent launch instead - if (!writeprotected) { - pid_t pid = fork(); - switch (pid) { - case -1: - writeLog("fork() failed!"); - return 1; - case 0: - execv(fullBinaryPath.c_str(), args.data()); - return 1; - } - } - - writeLog("Executed Telegram, closing log and quitting.."); + writeLog("Closing log and quitting.."); closeLog(); return 0; diff --git a/Telegram/SourceFiles/platform/linux/launcher_linux.cpp b/Telegram/SourceFiles/platform/linux/launcher_linux.cpp index 59b059fda..bef25c7f8 100644 --- a/Telegram/SourceFiles/platform/linux/launcher_linux.cpp +++ b/Telegram/SourceFiles/platform/linux/launcher_linux.cpp @@ -43,8 +43,6 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { } const auto justRelaunch = action == UpdaterLaunch::JustRelaunch; - const auto writeProtectedUpdate = action == UpdaterLaunch::PerformUpdate - && cWriteProtected(); const auto binaryPath = justRelaunch ? (cExeDir() + cExeName()).toStdString() @@ -53,31 +51,30 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { : (cExeDir() + u"Updater"_q)).toStdString(); std::vector argumentsList; - if (writeProtectedUpdate) { - argumentsList.push_back("pkexec"); - argumentsList.push_back("--keep-cwd"); - } else { + if (justRelaunch) { argumentsList.push_back(binaryPath); + } else if (cWriteProtected()) { + argumentsList.push_back("pkexec"); } argumentsList.push_back((justRelaunch && !arguments().isEmpty()) ? arguments().first().toStdString() : binaryPath); - if (cLaunchMode() == LaunchModeAutoStart) { - argumentsList.push_back("-autostart"); - } if (Logs::DebugEnabled()) { argumentsList.push_back("-debug"); } - if (cStartInTray()) { - argumentsList.push_back("-startintray"); - } - if (cDataFile() != u"data"_q) { - argumentsList.push_back("-key"); - argumentsList.push_back(cDataFile().toStdString()); - } if (justRelaunch) { + if (cLaunchMode() == LaunchModeAutoStart) { + argumentsList.push_back("-autostart"); + } + if (cStartInTray()) { + argumentsList.push_back("-startintray"); + } + if (cDataFile() != u"data"_q) { + argumentsList.push_back("-key"); + argumentsList.push_back(cDataFile().toStdString()); + } argumentsList.push_back("-noupdate"); argumentsList.push_back("-tosettings"); if (customWorkingDir()) { @@ -91,13 +88,6 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { argumentsList.push_back(cExeName().toStdString()); argumentsList.push_back("-exepath"); argumentsList.push_back(cExeDir().toStdString()); - if (!arguments().isEmpty()) { - argumentsList.push_back("-argv0"); - argumentsList.push_back(arguments().first().toStdString()); - } - if (customWorkingDir()) { - argumentsList.push_back("-workdir_custom"); - } if (cWriteProtected()) { argumentsList.push_back("-writeprotected"); } @@ -106,13 +96,24 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { Logs::closeMain(); CrashReports::Finish(); - // pkexec needs an alive parent - if (writeProtectedUpdate) { + if (justRelaunch) { + return GLib::spawn_async( + initialWorkingDir().toStdString(), + argumentsList, + std::nullopt, + GLib::SpawnFlags::FILE_AND_ARGV_ZERO_, + nullptr, + nullptr, + nullptr); + } else { if (!GLib::spawn_sync( - initialWorkingDir().toStdString(), argumentsList, std::nullopt, - GLib::SpawnFlags::SEARCH_PATH_, + // if the spawn is sync, working directory is not set + // and GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_ is set, + // it goes through an optimized code path + GLib::SpawnFlags::SEARCH_PATH_ + | GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_, nullptr, nullptr, nullptr, @@ -120,18 +121,8 @@ bool Launcher::launchUpdater(UpdaterLaunch action) { nullptr)) { return false; } - // launch new version in the same environment return launchUpdater(UpdaterLaunch::JustRelaunch); } - - return GLib::spawn_async( - initialWorkingDir().toStdString(), - argumentsList, - std::nullopt, - GLib::SpawnFlags::FILE_AND_ARGV_ZERO_, - nullptr, - nullptr, - nullptr); } } // namespace