log: Close file after stop and fallback to stderr

This commit is contained in:
PabloMK7
2026-01-19 21:01:55 +00:00
committed by OpenSauce
parent 6634b8c9d9
commit f71844b87f
+54 -21
View File
@@ -51,6 +51,8 @@ public:
virtual void EnableForStacktrace() = 0; virtual void EnableForStacktrace() = 0;
virtual void Flush() = 0; virtual void Flush() = 0;
virtual void Close() = 0;
}; };
/** /**
@@ -72,6 +74,10 @@ public:
std::fflush(stderr); std::fflush(stderr);
} }
void Close() override {
enabled = false;
}
void EnableForStacktrace() override { void EnableForStacktrace() override {
enabled = true; enabled = true;
} }
@@ -130,6 +136,11 @@ public:
file->Flush(); file->Flush();
} }
void Close() override {
file->Close();
enabled = false;
}
void EnableForStacktrace() override { void EnableForStacktrace() override {
enabled = true; enabled = true;
bytes_written = 0; bytes_written = 0;
@@ -158,6 +169,8 @@ public:
void Flush() override {} void Flush() override {}
void Close() override {}
void EnableForStacktrace() override {} void EnableForStacktrace() override {}
}; };
@@ -177,11 +190,14 @@ public:
void Flush() override {} void Flush() override {}
void Close() override {}
void EnableForStacktrace() override {} void EnableForStacktrace() override {}
}; };
#endif #endif
bool initialization_in_progress_suppress_logging = true; bool initialization_in_progress_suppress_logging = true;
bool logging_initialized = false;
#ifdef CITRA_LINUX_GCC_BACKTRACE #ifdef CITRA_LINUX_GCC_BACKTRACE
[[noreturn]] void SleepForever() { [[noreturn]] void SleepForever() {
@@ -216,6 +232,7 @@ public:
instance = std::unique_ptr<Impl, decltype(&Deleter)>( instance = std::unique_ptr<Impl, decltype(&Deleter)>(
new Impl(fmt::format("{}{}", log_dir, log_file), filter), Deleter); new Impl(fmt::format("{}{}", log_dir, log_file), filter), Deleter);
initialization_in_progress_suppress_logging = false; initialization_in_progress_suppress_logging = false;
logging_initialized = true;
} }
static void Start() { static void Start() {
@@ -258,8 +275,8 @@ public:
if (!filter.CheckMessage(log_class, log_level)) { if (!filter.CheckMessage(log_class, log_level)) {
return; return;
} }
Entry new_entry = Entry new_entry = CreateEntry(log_class, log_level, filename, line_num, function,
CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)); std::move(message), time_origin);
if (!regex_filter.empty() && if (!regex_filter.empty() &&
!boost::regex_search(FormatLogMessage(new_entry), regex_filter)) { !boost::regex_search(FormatLogMessage(new_entry), regex_filter)) {
return; return;
@@ -274,6 +291,24 @@ public:
} }
} }
static Entry CreateEntry(Class log_class, Level log_level, const char* filename,
unsigned int line_nr, const char* function, std::string&& message,
const std::chrono::steady_clock::time_point& time_origin) {
using std::chrono::duration_cast;
using std::chrono::microseconds;
using std::chrono::steady_clock;
return {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_nr,
.function = function,
.message = std::move(message),
};
}
private: private:
Impl(const std::string& file_backend_filename, const Filter& filter_) Impl(const std::string& file_backend_filename, const Filter& filter_)
: filter{filter_}, file_backend{file_backend_filename} { : filter{filter_}, file_backend{file_backend_filename} {
@@ -348,6 +383,8 @@ private:
}; };
while (!stop_token.stop_requested()) { while (!stop_token.stop_requested()) {
message_queue.PopWait(entry, stop_token); message_queue.PopWait(entry, stop_token);
// Only write the log if something was actually popped (entry.filename != nullptr)
// (for example, when the stop token is signaled).
if (entry.filename != nullptr) { if (entry.filename != nullptr) {
write_logs(); write_logs();
} }
@@ -367,24 +404,10 @@ private:
backend_thread.join(); backend_thread.join();
} }
ForEachBackend([](Backend& backend) { backend.Flush(); }); ForEachBackend([](Backend& backend) {
} backend.Flush();
backend.Close();
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, });
const char* function, std::string&& message) const {
using std::chrono::duration_cast;
using std::chrono::microseconds;
using std::chrono::steady_clock;
return {
.timestamp = duration_cast<microseconds>(steady_clock::now() - time_origin),
.log_class = log_class,
.log_level = log_level,
.filename = filename,
.line_num = line_nr,
.function = function,
.message = std::move(message),
};
} }
void ForEachBackend(auto lambda) { void ForEachBackend(auto lambda) {
@@ -485,9 +508,19 @@ void SetColorConsoleBackendEnabled(bool enabled) {
void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
unsigned int line_num, const char* function, fmt::string_view format, unsigned int line_num, const char* function, fmt::string_view format,
const fmt::format_args& args) { const fmt::format_args& args) {
if (!initialization_in_progress_suppress_logging) { if (initialization_in_progress_suppress_logging) [[unlikely]] {
return;
}
if (logging_initialized) [[likely]] {
Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
fmt::vformat(format, args)); fmt::vformat(format, args));
} else {
// In the rare case that logging occurs before initialization, write the
// message to stderr to preserve useful debug information.
Entry new_entry = Impl::CreateEntry(log_class, log_level, filename, line_num, function,
fmt::vformat(format, args), {});
PrintMessage(new_entry);
} }
} }
} // namespace Common::Log } // namespace Common::Log