Debugger: don't persist log.channel.set changes to the saved config

log.channel.set is meant for temporary, session-only diagnostic
tweaks (e.g. quieting a noisy channel while investigating something
over the WebSocket debugger). It was going through the same
SetLogLevel/SetEnabled calls the UI settings use, so a normal app
exit would persist whatever channels/levels the debugger last left
set, silently overwriting the user's real saved log preferences for
future runs - discovered when a later session's default logging
looked "off" for no apparent reason.

LogManager now tracks whether the debugger has touched channel
config this run and skips SaveConfig() entirely if so, leaving
whatever's already on disk untouched.
This commit is contained in:
Henrik Rydgård committed 2026-08-21 10:32:21 +02:00
1 parent e64ed141b3
commit c6061aebca
6 files changed
+30 -9

No files matched your search

+5
View File
@@ -729,6 +729,11 @@ bool CreateFullPath(const Path &path) {
return true;
}
if (path.empty()) {
ERROR_LOG(Log::IO, "Can't create an empty path");
return false;
}
switch (path.Type()) {
case PathType::NATIVE:
case PathType::CONTENT_URI:
+14 -7
View File
@@ -208,19 +208,26 @@ void LogManager::SetFileLogPath(const Path &filename) {
fp_ = nullptr;
}
logFilename_ = Path(filename);
if (!filename.empty()) {
logFilename_ = Path(filename);
if (outputs_ & LogOutput::File) {
File::CreateFullPath(logFilename_.NavigateUp());
fp_ = File::OpenCFile(logFilename_, "at");
logFileOpenFailed_ = fp_ == nullptr;
if (logFileOpenFailed_) {
printf("Failed to open log file %s\n", logFilename_.c_str());
if (outputs_ & LogOutput::File) {
File::CreateFullPath(logFilename_.NavigateUp());
fp_ = File::OpenCFile(logFilename_, "at");
logFileOpenFailed_ = fp_ == nullptr;
if (logFileOpenFailed_) {
printf("Failed to open log file %s\n", logFilename_.c_str());
}
}
}
}
void LogManager::SaveConfig(Section *section) {
if (channelsChangedByDebugger_) {
// Leave the section as whatever was already on disk - see the doc comment on
// NotifyChannelsChangedByDebugger().
return;
}
for (int i = 0; i < (int)Log::NUMBER_OF_LOGS; i++) {
section->Set((std::string(g_logTypeNames[i]) + "Enabled"), g_log[i].enabled);
section->Set((std::string(g_logTypeNames[i]) + "Level"), (int)g_log[i].level);
+6
View File
@@ -169,6 +169,11 @@ public:
void SaveConfig(Section *section);
void LoadConfig(const Section *section);
// Channel level/enabled changes made through the WebSocket debugger (log.channel.set) are
// meant as temporary, session-only diagnostic tweaks - call this so SaveConfig() skips
// writing (and thus permanently overwriting) the user's real saved settings with them.
void NotifyChannelsChangedByDebugger() { channelsChangedByDebugger_ = true; }
static const char *GetLogTypeName(Log type);
static u32 GetLevelColor(LogLevel level) {
@@ -189,6 +194,7 @@ private:
void operator=(const LogManager &) = delete;
bool initialized_ = false;
bool channelsChangedByDebugger_ = false;
#if PPSSPP_PLATFORM(WINDOWS)
ConsoleListener *consoleLog_ = nullptr;
@@ -119,6 +119,9 @@ void WebSocketLogChannelSet(DebuggerRequest &req) {
if (channelName != LogManager::GetLogTypeName(type))
continue;
// These are meant as temporary, session-only diagnostic tweaks - make sure they never
// get written back over the user's actual saved log settings.
g_logManager.NotifyChannelsChangedByDebugger();
if (hasLevel)
g_logManager.SetLogLevel(type, level);
if (hasEnabled)
+1 -1
View File
@@ -2199,7 +2199,7 @@ int __KernelStartModule(SceUID moduleId, u32 argsize, u32 argAddr, u32 returnVal
// TODO: Why do we skip smoption->attribute here?
SceUID threadID = __KernelCreateThread(module->nm.name, moduleId, entryAddr, priority, stacksize, attribute, 0, (module->nm.attribute & 0x1000) != 0);
_dbg_assert_(threadID > 0);
_dbg_assert_msg_(threadID > 0, "__KernelCreateThread returned %08x", threadID);
// TOOD: Check the return value and bail?
__KernelStartThreadValidate(threadID, argsize, argAddr);
__KernelSetThreadRA(threadID, NID_MODULERETURN);
+1 -1
View File
@@ -299,7 +299,7 @@ static int sceUsbMicInputInit(int unknown1, int inputVolume, int unknown2) {
}
static int sceUsbMicWaitInputEnd() {
ERROR_LOG(Log::HLE, "UNIMPL sceUsbMicWaitInputEnd");
WARN_LOG(Log::HLE, "UNIMPL sceUsbMicWaitInputEnd");
// Hack: Just task switch so other threads get to do work. Helps Beaterator (although recording does not appear to work correctly).
return hleDelayResult(0, "MicWait", 100);
}