From 67fab460500f0d3e4d7795a2002e853a41abbc2e Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Sat, 26 Sep 2026 10:32:07 +0300 Subject: [PATCH 1/2] Revert "#1681 Respect custom logfile during startup " This solution does not read UserLogFile as it isn't set yet and this is not the place to parse os-specific command line. This reverts commit 72f73ff62a6adef5caf5418a6c7d03a5c9867648. --- indra/newview/llappviewer.cpp | 86 +++-------------------------------- 1 file changed, 6 insertions(+), 80 deletions(-) diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 01ba5bdaa7..ee41c0f5f4 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -66,7 +66,6 @@ #include "llconversationlog.h" #if LL_WINDOWS #include "lldxhardware.h" -#include #endif #include "lltexturestats.h" #include "lltrace.h" @@ -2362,12 +2361,6 @@ void errorHandler(const std::string& title_string, const std::string& message_st } } -namespace -{ - std::string getStartupLogFileName(); - std::string getOldLogFileName(const std::string& log_file); -} - void LLAppViewer::initLoggingAndGetLastDuration() { // @@ -2399,10 +2392,13 @@ void LLAppViewer::initLoggingAndGetLastDuration() else { // Remove the last ".old" log file. - std::string log_file = getStartupLogFileName(); - std::string old_log_file = getOldLogFileName(log_file); + std::string old_log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + "SecondLife.old"); LLFile::remove(old_log_file); + // Get name of the log file + std::string log_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, + "SecondLife.log"); /* * Before touching any log files, compute the duration of the last run * by comparing the ctime of the previous start marker file with the ctime @@ -2449,7 +2445,7 @@ void LLAppViewer::initLoggingAndGetLastDuration() // Rename current log file to ".old" LLFile::rename(log_file, old_log_file); - // Set the log file. + // Set the log file to SecondLife.log LLError::logToFile(log_file); LL_INFOS() << "Started logging to " << log_file << LL_ENDL; if (!duration_log_msg.empty()) @@ -2588,76 +2584,6 @@ namespace LLStringUtil::null, OSMB_OK); } - - std::string getStartupLogFileName() - { - if (LLControlVariable* user_log_file = gSavedSettings.getControl("UserLogFile")) - { - std::string log_file = user_log_file->getValue().asString(); - if (!log_file.empty()) - { - return log_file; - } - } - -#if LL_WINDOWS - int argc = 0; - LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); - if (argv) - { - std::string log_file; - for (int i = 1; i < argc; ++i) - { - std::string option = ll_convert_wide_to_string(argv[i]); - if ((option == "--logfile" || option == "-logfile" || option == "/logfile") && - i + 1 < argc) - { - log_file = ll_convert_wide_to_string(argv[i + 1]); - } - else if (option.compare(0, 10, "--logfile=") == 0) - { - log_file = option.substr(10); - } - else if (option.compare(0, 9, "-logfile=") == 0) - { - log_file = option.substr(9); - } - else if (option.compare(0, 9, "/logfile:") == 0) - { - log_file = option.substr(9); - } - } - LocalFree(argv); - - if (!log_file.empty()) - { - return log_file; - } - } -#endif - - return gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"); - } - - std::string getOldLogFileName(const std::string& log_file) - { - std::string old_log_file = log_file; - size_t separator = old_log_file.find_last_of("/\\"); - size_t basename_start = (separator == std::string::npos) ? 0 : separator + 1; - size_t extension = old_log_file.find_last_of('.'); - - if (extension != std::string::npos && - extension > basename_start) - { - old_log_file.replace(extension, std::string::npos, ".old"); - } - else - { - old_log_file += ".old"; - } - - return old_log_file; - } } // anonymous namespace // Set a named control temporarily for this session, as when set via the command line --set option. From 3f87a02dd6467be44704a7175413dd3341ecaa4b Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Sat, 26 Sep 2026 00:08:52 +0300 Subject: [PATCH 2/2] #1681 Fix logfile option not applying --- indra/llfilesystem/lldir.cpp | 15 ++++++++--- indra/llfilesystem/lldir.h | 2 ++ indra/newview/llappviewer.cpp | 44 ++++++++++++++++++++++++++----- indra/newview/llviewercontrol.cpp | 43 ++++++++++++++++++++++++++++++ 4 files changed, 94 insertions(+), 10 deletions(-) diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index cfbf4361d1..e073ba78f8 100644 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -66,6 +66,7 @@ const char static const char* const empty = ""; std::string LLDir::sDumpDir = ""; +LLUUID LLDir::sDumpDirSessionID; LLDir::LLDir() : mAppName(""), @@ -320,11 +321,9 @@ const std::string &LLDir::getDumpDir() const { if (sDumpDir.empty() ) { - LLUUID uid; - uid.generate(); sDumpDir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "") - + "dump-" + uid.asString(); + + "dump-" + getDumpDirSessionUUID().asString(); dir_exists_or_crash(sDumpDir); } @@ -332,6 +331,16 @@ const std::string &LLDir::getDumpDir() const return LLDir::sDumpDir; } +const LLUUID& LLDir::getDumpDirSessionUUID() const +{ + if (sDumpDirSessionID.isNull()) + { + sDumpDirSessionID.generate(); + } + + return sDumpDirSessionID; +} + bool LLDir::dumpDirExists() const { return !sDumpDir.empty(); diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h index 0c17a91c3f..693b412bd8 100644 --- a/indra/llfilesystem/lldir.h +++ b/indra/llfilesystem/lldir.h @@ -90,6 +90,7 @@ class LLDir const std::string &getLindenUserDir() const; // Location of the Linden user dir. const std::string &getChatLogsDir() const; // Location of the chat logs dir. const std::string &getDumpDir() const; // Location of the per-run dump dir. + const LLUUID& getDumpDirSessionUUID() const; // UUID of the current dump dir. bool dumpDirExists() const; const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir. const std::string &getTempDir() const; // Common temporary directory @@ -280,6 +281,7 @@ class LLDir std::string mLanguage; // Current viewer language std::string mLLPluginDir; // Location for plugins and plugin shell static std::string sDumpDir; // Per-run crash report subdir of log directory. + static LLUUID sDumpDirSessionID; // UUID of the current dump dir. std::string mUserName; // Current user name }; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index ee41c0f5f4..8b06a215fe 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2380,13 +2380,7 @@ void LLAppViewer::initLoggingAndGetLastDuration() if (!gGPUBenchmarkMode) { LLFile::mkdir(gDirUtilp->getDumpLogsDirPath()); - - LLUUID uid; - uid.generate(); - // Is this even useful? - // Originally this wa used to store states, but I don't think it's practical with bugsplat attributes. - // So it just spams files now. - LLError::logToFile(gDirUtilp->getDumpLogsDirPath(uid.asString() + ".log")); + LLError::logToFile(gDirUtilp->getDumpLogsDirPath(gDirUtilp->getDumpDirSessionUUID().asString() + ".log")); } } else @@ -3101,6 +3095,42 @@ bool LLAppViewer::initConfiguration() loadColorSettings(); + // Command line could have updated UserLogFile + std::string log_filename = gSavedSettings.getString("UserLogFile"); + if (!log_filename.empty() && LLError::logFileName() != log_filename) + { + if (mSecondInstance) + { + // Second instances must not write to the primary + // instance's log file. + const LLUUID& uid = gDirUtilp->getDumpDirSessionUUID(); + std::string dir; + std::string base(log_filename); + + size_t slash_pos = log_filename.find_last_of("/\\"); + if (slash_pos != std::string::npos) + { + dir = log_filename.substr(0, slash_pos + 1); + base = log_filename.substr(slash_pos + 1); + } + + size_t dot_pos = base.find_last_of('.'); + if (dot_pos != std::string::npos) + { + base = base.substr(0, dot_pos) + "_" + uid.asString() + base.substr(dot_pos); + } + else + { + base += "_" + uid.asString(); + } + + log_filename = dir + base; + } + LLFile::remove(log_filename); + LLError::logToFile(log_filename); + LL_INFOS("Settings") << "Logging switched to " << log_filename << LL_ENDL; + } + // Let anyone else who cares know that we've populated our settings // variables. for (const auto& key : LLControlGroup::key_snapshot()) diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 6d825441ca..111eefc71f 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -527,9 +527,52 @@ static bool handleDebugViewsChanged(const LLSD& newvalue) static bool handleLogFileChanged(const LLSD& newvalue) { + // UserLogFile std::string log_filename = newvalue.asString(); + + if (LLAppViewer::instance()->isSecondInstance()) + { + // Second instances should not write to the primary + // instance's log file. Generate a unique dump log filename instead + if (log_filename.empty()) + { + // Restore defaults. + log_filename = gDirUtilp->getDumpLogsDirPath(gDirUtilp->getDumpDirSessionUUID().asString() + ".log"); + } + else + { + const LLUUID& uid = gDirUtilp->getDumpDirSessionUUID(); std::string dir; + std::string base(log_filename); + + size_t slash_pos = log_filename.find_last_of("/\\"); + if (slash_pos != std::string::npos) + { + dir = log_filename.substr(0, slash_pos + 1); + base = log_filename.substr(slash_pos + 1); + } + + size_t dot_pos = base.find_last_of('.'); + if (dot_pos != std::string::npos) + { + base = base.substr(0, dot_pos) + "_" + uid.asString() + base.substr(dot_pos); + } + else + { + base += "_" + uid.asString(); + } + + log_filename = dir + base; + } + } + else if (log_filename.empty()) + { + // Restore default log filename if user clears the setting + log_filename = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "SecondLife.log"); + } + LLFile::remove(log_filename); LLError::logToFile(log_filename); + LL_INFOS() << "Logging switched to " << log_filename << LL_ENDL; return true; }