Core: Only initialize logging once (#4509)

* Only initialize logging once

* Swap LOG macros for std::cerr and std::cout use.

* Add quick exit when trying to log before logger init

* Revert "Swap LOG macros for std::cerr and std::cout use."

This reverts commit a14d46d383.

* Use fmt's functions instead of cerr

Makes the commits a tad cleaner.

* Revert macro change

If I remember right, the if check here was to make sure we didn't throw exceptions after terminating the logger, which can happen due to a race involving some debug libSceVideoOut logs.

* Oops
This commit is contained in:
Stephen Miller 2026-06-02 01:03:18 -04:00 committed by GitHub
parent 87e774c4a1
commit 0b9eb3dd17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 37 additions and 65 deletions

View File

@ -78,13 +78,12 @@ bool KeyManager::LoadFromFile() {
SetDefaultKeys();
TransferTrophyKey();
SaveToFile();
LOG_DEBUG(KeyManager, "Created default key file: {}", keysPath.string());
return true;
}
std::ifstream file(keysPath);
if (!file.is_open()) {
LOG_ERROR(KeyManager, "Could not open key file: {}", keysPath.string());
fmt::println("Could not open key file: {}", keysPath.string());
return false;
}
@ -104,12 +103,10 @@ bool KeyManager::LoadFromFile() {
SaveToFile();
}
}
LOG_DEBUG(KeyManager, "Successfully loaded keys from: {}", keysPath.string());
return true;
} catch (const std::exception& e) {
LOG_ERROR(KeyManager, "Error loading keys, using defaults: {}", e.what());
fmt::println("Error loading keys, using defaults: {}", e.what());
SetDefaultKeys();
return false;
}
@ -125,7 +122,7 @@ bool KeyManager::SaveToFile() {
std::ofstream file(keysPath);
if (!file.is_open()) {
LOG_ERROR(KeyManager, "Could not open key file for writing: {}", keysPath.string());
fmt::println("Could not open key file for writing: {}", keysPath.string());
return false;
}
@ -133,15 +130,13 @@ bool KeyManager::SaveToFile() {
file.flush();
if (file.fail()) {
LOG_ERROR(KeyManager, "Failed to write keys to: {}", keysPath.string());
fmt::println("Failed to write keys to: {}", keysPath.string());
return false;
}
LOG_DEBUG(KeyManager, "Successfully saved keys to: {}", keysPath.string());
return true;
} catch (const std::exception& e) {
LOG_ERROR(KeyManager, "Error saving keys: {}", e.what());
fmt::println("Error saving keys: {}", e.what());
return false;
}
}

View File

@ -3,6 +3,7 @@
#pragma once
#include <iostream>
#include <unordered_map>
#include <vector>
#include <spdlog/details/fmt_helper.h>

View File

@ -89,12 +89,11 @@ std::optional<T> get_optional(const toml::value& v, const std::string& key) {
void EmulatorSettingsImpl::PrintChangedSummary(const std::vector<std::string>& changed) {
if (changed.empty()) {
LOG_DEBUG(Config, "No game-specific overrides applied");
return;
}
LOG_DEBUG(Config, "Game-specific overrides applied:");
fmt::println("Game-specific overrides applied:");
for (const auto& k : changed)
LOG_DEBUG(Config, " * {}", k);
fmt::println(" * {}", k);
}
// ── Singleton ────────────────────────────────────────────────────────
@ -232,7 +231,6 @@ void EmulatorSettingsImpl::ClearGameSpecificOverrides() {
ClearGroupOverrides(m_audio);
ClearGroupOverrides(m_gpu);
ClearGroupOverrides(m_vulkan);
LOG_DEBUG(Config, "All game-specific overrides cleared");
}
void EmulatorSettingsImpl::ResetGameSpecificValue(const std::string& key) {
@ -260,7 +258,7 @@ void EmulatorSettingsImpl::ResetGameSpecificValue(const std::string& key) {
return;
if (tryGroup(m_vulkan))
return;
LOG_WARNING(Config, "ResetGameSpecificValue: key '{}' not found", key);
fmt::println("ResetGameSpecificValue: key '{}' not found", key);
}
bool EmulatorSettingsImpl::Save(const std::string& serial) {
@ -302,7 +300,7 @@ bool EmulatorSettingsImpl::Save(const std::string& serial) {
std::ofstream out(path);
if (!out) {
LOG_ERROR(Config, "Failed to open game config for writing: {}", path.string());
fmt::println("Failed to open game config for writing: {}", path.string());
return false;
}
out << std::setw(2) << j;
@ -344,14 +342,14 @@ bool EmulatorSettingsImpl::Save(const std::string& serial) {
std::ofstream out(path);
if (!out) {
LOG_ERROR(Config, "Failed to open config for writing: {}", path.string());
fmt::println("Failed to open config for writing: {}", path.string());
return false;
}
out << std::setw(2) << existing;
return !out.fail();
}
} catch (const std::exception& e) {
LOG_ERROR(Config, "Error saving settings: {}", e.what());
fmt::println("Error saving settings: {}", e.what());
return false;
}
}
@ -364,7 +362,6 @@ bool EmulatorSettingsImpl::Load(const std::string& serial) {
// ── Global config ──────────────────────────────────────────
const auto userDir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
const auto configPath = userDir / "config.json";
LOG_DEBUG(Config, "Loading global config from: {}", configPath.string());
if (std::ifstream in{configPath}; in.good()) {
json gj;
@ -385,8 +382,6 @@ bool EmulatorSettingsImpl::Load(const std::string& serial) {
mergeGroup(m_audio, "Audio");
mergeGroup(m_gpu, "GPU");
mergeGroup(m_vulkan, "Vulkan");
LOG_DEBUG(Config, "Global config loaded successfully");
} else {
if (std::filesystem::exists(Common::FS::GetUserPath(Common::FS::PathType::UserDir) /
"config.toml")) {
@ -420,7 +415,6 @@ bool EmulatorSettingsImpl::Load(const std::string& serial) {
}
}
}
LOG_DEBUG(Config, "Global config not found - using defaults");
SetDefaultValues();
Save();
}
@ -436,16 +430,13 @@ bool EmulatorSettingsImpl::Load(const std::string& serial) {
// base configuration.
const auto gamePath =
Common::FS::GetUserPath(Common::FS::PathType::CustomConfigs) / (serial + ".json");
LOG_DEBUG(Config, "Applying game config: {}", gamePath.string());
if (!std::filesystem::exists(gamePath)) {
LOG_DEBUG(Config, "No game-specific config found for {}", serial);
return false;
}
std::ifstream in(gamePath);
if (!in) {
LOG_ERROR(Config, "Failed to open game config: {}", gamePath.string());
return false;
}
@ -478,7 +469,7 @@ bool EmulatorSettingsImpl::Load(const std::string& serial) {
return true;
}
} catch (const std::exception& e) {
LOG_ERROR(Config, "Error loading settings: {}", e.what());
fmt::println("Error loading settings: {}", e.what());
return false;
}
}
@ -678,7 +669,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
}
s.install_dirs.value = settings_install_dirs;
} catch (const std::exception& e) {
LOG_WARNING(Config, "Failed to transfer install directories: {}", e.what());
fmt::println("Failed to transfer install directories: {}", e.what());
}
// Transfer addon install directory
@ -694,7 +685,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
}
}
} catch (const std::exception& e) {
LOG_WARNING(Config, "Failed to transfer addon install directory: {}", e.what());
fmt::println("Failed to transfer addon install directory: {}", e.what());
}
}
if (og_data.contains("General")) {
@ -713,7 +704,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
}
}
} catch (const std::exception& e) {
LOG_WARNING(Config, "Failed to transfer sysmodules install directory: {}", e.what());
fmt::println("Failed to transfer sysmodules install directory: {}", e.what());
}
// Transfer font install directory
@ -729,7 +720,7 @@ bool EmulatorSettingsImpl::TransferSettings() {
}
}
} catch (const std::exception& e) {
LOG_WARNING(Config, "Failed to transfer font install directory: {}", e.what());
fmt::println("Failed to transfer font install directory: {}", e.what());
}
}

View File

@ -116,26 +116,20 @@ inline OverrideItem make_override(const char* key, Setting<T> Struct::* member)
return OverrideItem{
key,
[member, key](void* base, const nlohmann::json& entry, std::vector<std::string>& changed) {
LOG_DEBUG(Config, "[make_override] Processing key: {}", key);
LOG_DEBUG(Config, "[make_override] Entry JSON: {}", entry.dump());
Struct* obj = reinterpret_cast<Struct*>(base);
Setting<T>& dst = obj->*member;
try {
T newValue = entry.get<T>();
LOG_DEBUG(Config, "[make_override] Parsed value: {}", newValue);
LOG_DEBUG(Config, "[make_override] Current value: {}", dst.value);
if (dst.value != newValue) {
std::ostringstream oss;
oss << key << " ( " << dst.value << " " << newValue << " )";
oss << key << " ( " << dst.value << " -> " << newValue << " )";
changed.push_back(oss.str());
LOG_DEBUG(Config, "[make_override] Recorded change: {}", oss.str());
}
dst.game_specific_value = newValue;
LOG_DEBUG(Config, "[make_override] Successfully updated {}", key);
} catch (const std::exception& e) {
LOG_ERROR(Config, "[make_override] ERROR parsing {}: {}", key, e.what());
LOG_ERROR(Config, "[make_override] Entry was: {}", entry.dump());
LOG_ERROR(Config, "[make_override] Type name: {}", entry.type_name());
fmt::println("[make_override] error parsing {}: {}", key, e.what());
fmt::println("[make_override] Entry was: {}", entry.dump());
fmt::println("[make_override] Type name: {}", entry.type_name());
}
},

View File

@ -59,13 +59,13 @@ bool UserSettingsImpl::Save() const {
std::ofstream out(path);
if (!out) {
LOG_ERROR(Config, "Failed to open user settings for writing: {}", path.string());
fmt::println("Failed to open user settings for writing: {}", path.string());
return false;
}
out << std::setw(2) << existing;
return !out.fail();
} catch (const std::exception& e) {
LOG_ERROR(Config, "Error saving user settings: {}", e.what());
fmt::println("Error saving user settings: {}", e.what());
return false;
}
}
@ -74,7 +74,6 @@ bool UserSettingsImpl::Load() {
const auto path = Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "users.json";
try {
if (!std::filesystem::exists(path)) {
LOG_DEBUG(Config, "User settings file not found: {}", path.string());
if (m_userManager.GetUsers().user.empty())
m_userManager.GetUsers() = m_userManager.CreateDefaultUsers();
m_loaded = true;
@ -84,7 +83,7 @@ bool UserSettingsImpl::Load() {
std::ifstream in(path);
if (!in) {
LOG_ERROR(Config, "Failed to open user settings: {}", path.string());
fmt::println("Failed to open user settings: {}", path.string());
return false;
}
@ -103,15 +102,13 @@ bool UserSettingsImpl::Load() {
m_userManager.GetUsers() = default_users;
}
LOG_DEBUG(Config, "User settings loaded successfully");
m_loaded = true;
if (m_userManager.GetUsers().commit_hash != Common::g_scm_rev)
Save();
return true;
} catch (const std::exception& e) {
LOG_ERROR(Config, "Error loading user settings: {}", e.what());
fmt::println("Error loading user settings: {}", e.what());
if (m_userManager.GetUsers().user.empty())
m_userManager.GetUsers() = m_userManager.CreateDefaultUsers();
return false;

View File

@ -252,6 +252,11 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
}
}
// Initialize logging as soon as possible
EmulatorSettings.Load(id);
Common::Log::Setup((!id.empty() && EmulatorSettings.IsLogSeparate()) ? id + ".log"
: "shad_log.txt");
auto guest_eboot_path = "/app0/" + eboot_name.generic_string();
const auto eboot_path = mnt->GetHostPath(guest_eboot_path);
@ -271,12 +276,6 @@ void Emulator::Run(std::filesystem::path file, std::vector<std::string> args,
}
game_info.game_folder = game_folder;
EmulatorSettings.Load(id);
Common::Log::Shutdown();
// Initialize logging as soon as possible
Common::Log::Setup((!id.empty() && EmulatorSettings.IsLogSeparate()) ? id + ".log"
: "shad_log.txt");
if (!std::filesystem::exists(file)) {
LOG_CRITICAL(Loader, "eboot.bin does not exist: {}",

View File

@ -115,18 +115,18 @@ SDL_Texture* LoadSdlTextureData(std::vector<u8> data) {
unsigned char* image_data = stbi_load_from_memory(
(const unsigned char*)data.data(), (int)data.size(), &image_width, &image_height, NULL, 4);
if (image_data == nullptr) {
LOG_ERROR(ImGui, "Failed to load image: {}", stbi_failure_reason());
fmt::println("Failed to load image: {}", stbi_failure_reason());
}
SDL_Surface* surface = SDL_CreateSurfaceFrom(image_width, image_height, SDL_PIXELFORMAT_RGBA32,
(void*)image_data, channels * image_width);
if (surface == nullptr) {
LOG_ERROR(ImGui, "Unable to create SDL surface: {}", SDL_GetError());
fmt::println("Unable to create SDL surface: {}", SDL_GetError());
}
SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
if (texture == nullptr) {
LOG_ERROR(ImGui, "Unable to create SDL texture: {}", SDL_GetError());
fmt::println("Unable to create SDL texture: {}", SDL_GetError());
}
SDL_DestroySurface(surface);
@ -190,13 +190,13 @@ void GetGameIconInfo(std::vector<IconInfo>& icons) {
void Launch(char* executableName) {
if (!SDL_Init(SDL_INIT_VIDEO)) {
LOG_ERROR(ImGui, "SDL_INIT_VIDEO Error: {}", SDL_GetError());
fmt::println("SDL_INIT_VIDEO Error: {}", SDL_GetError());
SDL_Quit();
return;
}
if (!SDL_Init(SDL_INIT_GAMEPAD)) {
LOG_ERROR(ImGui, "SDL_INIT_GAMEPAD Error: {}", SDL_GetError());
fmt::println("SDL_INIT_GAMEPAD Error: {}", SDL_GetError());
}
SDL_Window* window =
@ -204,7 +204,7 @@ void Launch(char* executableName) {
renderer = SDL_CreateRenderer(window, nullptr);
if (window == nullptr) {
LOG_ERROR(ImGui, "SDL Window Creation Error: {}", SDL_GetError());
fmt::println("SDL Window Creation Error: {}", SDL_GetError());
SDL_DestroyRenderer(renderer);
SDL_Quit();
return;

View File

@ -103,9 +103,6 @@ int main(int argc, char* argv[]) {
if (waitPid)
Core::Debugger::WaitForPid(*waitPid);
// Start default log
Common::Log::Setup("shad_log.txt");
IPC::Instance().Init();
auto emu_state = std::make_shared<EmulatorState>();
@ -121,10 +118,8 @@ int main(int argc, char* argv[]) {
EmulatorSettingsImpl::SetInstance(emu_settings);
emu_settings->Load();
Common::Log::Shutdown();
// Start configured log
// Configure logger appropriately
Common::Log::g_should_append |= EmulatorSettings.IsLogAppend();
Common::Log::Setup("shad_log.txt");
if (bigPicture) {
BigPictureMode::Launch(argv[0]);