feat(diagnostics): make the logging + crash infrastructure actually work (W7-2, W7-3, W7-4)
The Foundation tier — answers the original "make it easier to diagnose problems" ask. - W7-2 (keystone): the app-level Logger file sink was never initialized, so LOG/LOGF/ VERBOSE_LOGF went nowhere and dragonx-debug.log didn't exist on Linux/macOS at all. main() now calls Logger::init(<config>/dragonx-debug.log) on every platform. Fixed a latent deadlock this exposed: init() wrote its banner via write(), which re-locks the non-recursive mutex_ it already holds — now written directly. On Windows the raw stdout/stderr freopen moved to a separate dragonx-stdout.log so the two writers don't contend on one file. Added testLoggerFileSink (also a deadlock guard — it would hang if the fix regressed). - W7-3: no crash handler existed on Linux/macOS. Added an async-signal-safe sigaction handler (SIGSEGV/ABRT/BUS/FPE/ILL) that writes the signal id + a backtrace_symbols_fd backtrace to dragonx-crash.log, then re-raises the default disposition for a core dump — the POSIX counterpart of the Windows SEH filter. - W7-4: Logger::init now rotates the log to a single .1 backup past 10 MB, so a long or verbose session can't grow it unbounded. Build-clean; ctest 1/1. Remaining Foundation: the QoL bundle (mostly UI). See docs/wallet-hardening.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -5,10 +5,12 @@
|
||||
#include "logger.h"
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <ctime>
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
namespace dragonx {
|
||||
namespace util {
|
||||
@@ -35,14 +37,30 @@ bool Logger::init(const std::string& path)
|
||||
if (file_.is_open()) {
|
||||
file_.close();
|
||||
}
|
||||
|
||||
|
||||
// W7-4: cap the log's growth — if the existing file is already large, rotate it to a single .1
|
||||
// backup before reopening in append mode, so a long-lived or verbose session can't grow it
|
||||
// without bound.
|
||||
{
|
||||
std::error_code ec;
|
||||
const auto sz = std::filesystem::file_size(path, ec);
|
||||
constexpr std::uintmax_t kMaxLogBytes = 10ull * 1024ull * 1024ull; // 10 MB
|
||||
if (!ec && sz > kMaxLogBytes) {
|
||||
std::filesystem::rename(path, path + ".1", ec); // replaces any previous .1 backup
|
||||
if (ec) std::filesystem::remove(path, ec); // fall back to truncation if rename fails
|
||||
}
|
||||
}
|
||||
|
||||
file_.open(path, std::ios::out | std::ios::app);
|
||||
initialized_ = file_.is_open();
|
||||
|
||||
|
||||
if (initialized_) {
|
||||
write("=== Logger initialized ===");
|
||||
// Write the banner directly, NOT via write(): write() re-locks the non-recursive mutex_ we
|
||||
// already hold here, which would deadlock (latent — init() was previously never called, W7-2).
|
||||
file_ << "=== Logger initialized ===" << std::endl;
|
||||
file_.flush();
|
||||
}
|
||||
|
||||
|
||||
return initialized_;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user