Logger System 0.1.3
High-performance C++20 thread-safe logging system with asynchronous capabilities
Loading...
Searching...
No Matches
kcenon::logger::safety::crash_safe_logger Class Reference

Logger with crash recovery and emergency flush capabilities. More...

#include <crash_safe_logger.h>

Collaboration diagram for kcenon::logger::safety::crash_safe_logger:
Collaboration graph

Public Member Functions

bool install_crash_handlers ()
 Install signal handlers for crash detection.
 
void uninstall_crash_handlers ()
 Remove signal handlers.
 
bool flush_with_timeout (std::chrono::milliseconds timeout)
 Flush with timeout to prevent deadlocks.
 
void emergency_flush ()
 Emergency flush (async-signal-safe)
 
void set_min_level (log_level level)
 Set minimum log level (thread-safe)
 
log_level get_min_level () const
 Get minimum log level (thread-safe)
 
void set_auto_flush_interval (std::chrono::milliseconds interval)
 Enable auto-flush at regular intervals.
 
void log (log_level level, const std::string &message)
 Log message (delegates to underlying logger)
 
void log (log_level level, const std::string &message, const std::string &file, int line, const std::string &function)
 Log message with source location.
 
common::VoidResult start ()
 Start the underlying logger.
 
common::VoidResult stop ()
 Stop the underlying logger.
 
std::shared_ptr< loggerget_underlying_logger ()
 Get the underlying logger.
 
 ~crash_safe_logger ()
 

Static Public Member Functions

static std::shared_ptr< crash_safe_loggercreate (std::shared_ptr< logger > underlying_logger=nullptr)
 Create crash-safe logger.
 

Private Member Functions

 crash_safe_logger (std::shared_ptr< logger > logger)
 
void start_auto_flush_thread ()
 Start auto-flush background thread.
 
void stop_auto_flush_thread ()
 Stop auto-flush background thread.
 

Static Private Member Functions

static void signal_handler (int signal)
 Signal handler (async-signal-safe)
 

Private Attributes

std::shared_ptr< loggerlogger_
 
std::atomic< log_level > min_level_
 
std::mutex handler_mutex_
 
bool handlers_installed_
 
struct sigaction old_sigsegv_
 
struct sigaction old_sigabrt_
 
struct sigaction old_sigterm_
 
struct sigaction old_sigint_
 
std::atomic< bool > emergency_flush_active_
 
std::atomic< bool > flush_requested_
 
std::mutex flush_mutex_
 
std::chrono::milliseconds auto_flush_interval_
 
std::thread auto_flush_thread_
 
std::atomic< bool > stop_auto_flush_
 

Static Private Attributes

static std::weak_ptr< crash_safe_loggerglobal_instance_
 

Detailed Description

Logger with crash recovery and emergency flush capabilities.

This logger wrapper provides additional safety guarantees:

  • Signal handlers for crash detection (SIGSEGV, SIGABRT, SIGTERM)
  • Emergency synchronous flush on crash
  • Atomic log level management
  • Flush with timeout to prevent deadlocks
  • Periodic auto-flush for data durability

Thread Safety

All methods are thread-safe. Signal handlers use async-signal-safe operations only.

Production Usage

// Create crash-safe logger
// Enable crash handlers
logger->install_crash_handlers();
// Configure auto-flush
logger->set_auto_flush_interval(std::chrono::seconds(5));
// Use as normal logger
logger->log(log_level::info, "Application started");
// On crash, logs are automatically flushed
static std::shared_ptr< crash_safe_logger > create(std::shared_ptr< logger > underlying_logger=nullptr)
Create crash-safe logger.

Limitations

  • Signal handlers cannot allocate memory
  • Emergency flush is best-effort only
  • May not work with all crash scenarios (e.g., stack corruption)
See also
logger Underlying logger being wrapped for crash safety
output_sink_interface Sinks that receive emergency flushed logs

Definition at line 61 of file crash_safe_logger.h.

Constructor & Destructor Documentation

◆ ~crash_safe_logger()

kcenon::logger::safety::crash_safe_logger::~crash_safe_logger ( )
inline

Definition at line 254 of file crash_safe_logger.h.

254 {
257 }
void stop_auto_flush_thread()
Stop auto-flush background thread.
void uninstall_crash_handlers()
Remove signal handlers.

References stop_auto_flush_thread(), and uninstall_crash_handlers().

Here is the call graph for this function:

◆ crash_safe_logger()

kcenon::logger::safety::crash_safe_logger::crash_safe_logger ( std::shared_ptr< logger > logger)
inlineexplicitprivate

Definition at line 260 of file crash_safe_logger.h.

261 : logger_(std::move(logger))
262 , min_level_(log_level::info)
263 , handlers_installed_(false)
265 , flush_requested_(false)
267 , stop_auto_flush_(false)
268 {
269 }

Referenced by create().

Here is the caller graph for this function:

Member Function Documentation

◆ create()

static std::shared_ptr< crash_safe_logger > kcenon::logger::safety::crash_safe_logger::create ( std::shared_ptr< logger > underlying_logger = nullptr)
inlinestatic

Create crash-safe logger.

Parameters
underlying_loggerBase logger to wrap (optional)
Returns
Shared pointer to crash_safe_logger

Definition at line 68 of file crash_safe_logger.h.

70 {
71 if (!underlying_logger) {
72 underlying_logger = std::make_shared<logger>(true, 16384);
73 }
74
75 auto safe_logger = std::shared_ptr<crash_safe_logger>(
76 new crash_safe_logger(std::move(underlying_logger))
77 );
78
79 // Register for cleanup
80 global_instance_ = safe_logger;
81
82 return safe_logger;
83 }
static std::weak_ptr< crash_safe_logger > global_instance_
crash_safe_logger(std::shared_ptr< logger > logger)

References crash_safe_logger(), and global_instance_.

Here is the call graph for this function:

◆ emergency_flush()

void kcenon::logger::safety::crash_safe_logger::emergency_flush ( )
inline

Emergency flush (async-signal-safe)

This is called from signal handlers and must be async-signal-safe. It attempts a best-effort flush without allocations or locks.

Definition at line 165 of file crash_safe_logger.h.

165 {
166 // Set emergency flag
167 emergency_flush_active_.store(true, std::memory_order_release);
168
169 // Try immediate flush (may fail if locks are held)
170 if (flush_mutex_.try_lock()) {
171 logger_->flush();
172 flush_mutex_.unlock();
173 }
174 }

References emergency_flush_active_, flush_mutex_, and logger_.

◆ flush_with_timeout()

bool kcenon::logger::safety::crash_safe_logger::flush_with_timeout ( std::chrono::milliseconds timeout)
inline

Flush with timeout to prevent deadlocks.

Parameters
timeoutMaximum time to wait for flush
Returns
true if flushed successfully, false on timeout

Definition at line 135 of file crash_safe_logger.h.

135 {
136 auto deadline = std::chrono::steady_clock::now() + timeout;
137
138 // Signal flush request
139 flush_requested_.store(true, std::memory_order_release);
140
141 // Try to acquire flush lock with timeout
142 while (std::chrono::steady_clock::now() < deadline) {
143 if (flush_mutex_.try_lock()) {
144 // Got lock, perform flush
145 logger_->flush();
146 flush_mutex_.unlock();
147 flush_requested_.store(false, std::memory_order_release);
148 return true;
149 }
150
151 // Wait a bit before retry
152 std::this_thread::sleep_for(std::chrono::milliseconds(10));
153 }
154
155 // Timeout occurred
156 return false;
157 }

References flush_mutex_, flush_requested_, and logger_.

Referenced by start_auto_flush_thread().

Here is the caller graph for this function:

◆ get_min_level()

log_level kcenon::logger::safety::crash_safe_logger::get_min_level ( ) const
inline

Get minimum log level (thread-safe)

Definition at line 187 of file crash_safe_logger.h.

187 {
188 return min_level_.load(std::memory_order_acquire);
189 }

References min_level_.

◆ get_underlying_logger()

std::shared_ptr< logger > kcenon::logger::safety::crash_safe_logger::get_underlying_logger ( )
inline

Get the underlying logger.

Definition at line 250 of file crash_safe_logger.h.

250 {
251 return logger_;
252 }

References logger_.

◆ install_crash_handlers()

bool kcenon::logger::safety::crash_safe_logger::install_crash_handlers ( )
inline

Install signal handlers for crash detection.

Returns
true if handlers installed successfully

Definition at line 89 of file crash_safe_logger.h.

89 {
90 std::lock_guard<std::mutex> lock(handler_mutex_);
91
93 return true; // Already installed
94 }
95
96 // Install handlers for common crash signals
97 struct sigaction sa;
98 sa.sa_handler = &crash_safe_logger::signal_handler;
99 sigemptyset(&sa.sa_mask);
100 sa.sa_flags = SA_RESTART;
101
102 bool success = true;
103 success &= (sigaction(SIGSEGV, &sa, &old_sigsegv_) == 0);
104 success &= (sigaction(SIGABRT, &sa, &old_sigabrt_) == 0);
105 success &= (sigaction(SIGTERM, &sa, &old_sigterm_) == 0);
106 success &= (sigaction(SIGINT, &sa, &old_sigint_) == 0);
107
109 return success;
110 }
static void signal_handler(int signal)
Signal handler (async-signal-safe)

References handler_mutex_, handlers_installed_, old_sigabrt_, old_sigint_, old_sigsegv_, old_sigterm_, signal_handler(), and kcenon::logger::success.

Here is the call graph for this function:

◆ log() [1/2]

void kcenon::logger::safety::crash_safe_logger::log ( log_level level,
const std::string & message )
inline

Log message (delegates to underlying logger)

Definition at line 208 of file crash_safe_logger.h.

208 {
209 // Early exit if level not enabled
210 if (level < min_level_.load(std::memory_order_acquire)) {
211 return;
212 }
213
214 logger_->log(level, message);
215 }

References logger_, and min_level_.

◆ log() [2/2]

void kcenon::logger::safety::crash_safe_logger::log ( log_level level,
const std::string & message,
const std::string & file,
int line,
const std::string & function )
inline

Log message with source location.

Definition at line 220 of file crash_safe_logger.h.

224 {
225 if (level < min_level_.load(std::memory_order_acquire)) {
226 return;
227 }
228
229 logger_->log(level, message, file, line, function);
230 }

References logger_, and min_level_.

◆ set_auto_flush_interval()

void kcenon::logger::safety::crash_safe_logger::set_auto_flush_interval ( std::chrono::milliseconds interval)
inline

Enable auto-flush at regular intervals.

Parameters
intervalTime between auto-flushes

Definition at line 195 of file crash_safe_logger.h.

195 {
196 auto_flush_interval_ = interval;
197
198 if (interval.count() > 0 && !auto_flush_thread_.joinable()) {
200 } else if (interval.count() == 0 && auto_flush_thread_.joinable()) {
202 }
203 }
void start_auto_flush_thread()
Start auto-flush background thread.

References auto_flush_interval_, auto_flush_thread_, start_auto_flush_thread(), and stop_auto_flush_thread().

Here is the call graph for this function:

◆ set_min_level()

void kcenon::logger::safety::crash_safe_logger::set_min_level ( log_level level)
inline

Set minimum log level (thread-safe)

Definition at line 179 of file crash_safe_logger.h.

179 {
180 min_level_.store(level, std::memory_order_release);
181 logger_->set_min_level(level);
182 }

References logger_, and min_level_.

◆ signal_handler()

static void kcenon::logger::safety::crash_safe_logger::signal_handler ( int signal)
inlinestaticprivate

Signal handler (async-signal-safe)

Definition at line 274 of file crash_safe_logger.h.

274 {
275 // Get global instance
276 auto instance = global_instance_.lock();
277 if (!instance) {
278 return; // Logger already destroyed
279 }
280
281 // Perform emergency flush
282 instance->emergency_flush();
283
284 // Chain to old handler if exists
285 switch (signal) {
286 case SIGSEGV:
287 if (instance->old_sigsegv_.sa_handler != SIG_DFL &&
288 instance->old_sigsegv_.sa_handler != SIG_IGN) {
289 instance->old_sigsegv_.sa_handler(signal);
290 }
291 break;
292 case SIGABRT:
293 if (instance->old_sigabrt_.sa_handler != SIG_DFL &&
294 instance->old_sigabrt_.sa_handler != SIG_IGN) {
295 instance->old_sigabrt_.sa_handler(signal);
296 }
297 break;
298 case SIGTERM:
299 case SIGINT:
300 // For these, we exit after flush
301 std::exit(signal);
302 break;
303 }
304 }

References global_instance_.

Referenced by install_crash_handlers().

Here is the caller graph for this function:

◆ start()

common::VoidResult kcenon::logger::safety::crash_safe_logger::start ( )
inline

Start the underlying logger.

Definition at line 235 of file crash_safe_logger.h.

235 {
236 return logger_->start();
237 }

References logger_.

◆ start_auto_flush_thread()

void kcenon::logger::safety::crash_safe_logger::start_auto_flush_thread ( )
inlineprivate

Start auto-flush background thread.

Definition at line 309 of file crash_safe_logger.h.

309 {
310 stop_auto_flush_ = false;
311 auto_flush_thread_ = std::thread([this]() {
312 while (!stop_auto_flush_.load(std::memory_order_acquire)) {
313 std::this_thread::sleep_for(auto_flush_interval_);
314
315 if (!stop_auto_flush_.load(std::memory_order_acquire)) {
316 flush_with_timeout(std::chrono::seconds(1));
317 }
318 }
319 });
320 }
bool flush_with_timeout(std::chrono::milliseconds timeout)
Flush with timeout to prevent deadlocks.

References auto_flush_interval_, auto_flush_thread_, flush_with_timeout(), and stop_auto_flush_.

Referenced by set_auto_flush_interval().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stop()

common::VoidResult kcenon::logger::safety::crash_safe_logger::stop ( )
inline

Stop the underlying logger.

Definition at line 242 of file crash_safe_logger.h.

242 {
244 return logger_->stop();
245 }

References logger_, and stop_auto_flush_thread().

Here is the call graph for this function:

◆ stop_auto_flush_thread()

void kcenon::logger::safety::crash_safe_logger::stop_auto_flush_thread ( )
inlineprivate

Stop auto-flush background thread.

Definition at line 325 of file crash_safe_logger.h.

325 {
326 if (auto_flush_thread_.joinable()) {
327 stop_auto_flush_.store(true, std::memory_order_release);
328 auto_flush_thread_.join();
329 }
330 }

References auto_flush_thread_, and stop_auto_flush_.

Referenced by set_auto_flush_interval(), stop(), and ~crash_safe_logger().

Here is the caller graph for this function:

◆ uninstall_crash_handlers()

void kcenon::logger::safety::crash_safe_logger::uninstall_crash_handlers ( )
inline

Remove signal handlers.

Definition at line 115 of file crash_safe_logger.h.

115 {
116 std::lock_guard<std::mutex> lock(handler_mutex_);
117
118 if (!handlers_installed_) {
119 return;
120 }
121
122 sigaction(SIGSEGV, &old_sigsegv_, nullptr);
123 sigaction(SIGABRT, &old_sigabrt_, nullptr);
124 sigaction(SIGTERM, &old_sigterm_, nullptr);
125 sigaction(SIGINT, &old_sigint_, nullptr);
126
127 handlers_installed_ = false;
128 }

References handler_mutex_, handlers_installed_, old_sigabrt_, old_sigint_, old_sigsegv_, and old_sigterm_.

Referenced by ~crash_safe_logger().

Here is the caller graph for this function:

Member Data Documentation

◆ auto_flush_interval_

std::chrono::milliseconds kcenon::logger::safety::crash_safe_logger::auto_flush_interval_
private

Definition at line 350 of file crash_safe_logger.h.

Referenced by set_auto_flush_interval(), and start_auto_flush_thread().

◆ auto_flush_thread_

std::thread kcenon::logger::safety::crash_safe_logger::auto_flush_thread_
private

◆ emergency_flush_active_

std::atomic<bool> kcenon::logger::safety::crash_safe_logger::emergency_flush_active_
private

Definition at line 345 of file crash_safe_logger.h.

Referenced by emergency_flush().

◆ flush_mutex_

std::mutex kcenon::logger::safety::crash_safe_logger::flush_mutex_
private

Definition at line 347 of file crash_safe_logger.h.

Referenced by emergency_flush(), and flush_with_timeout().

◆ flush_requested_

std::atomic<bool> kcenon::logger::safety::crash_safe_logger::flush_requested_
private

Definition at line 346 of file crash_safe_logger.h.

Referenced by flush_with_timeout().

◆ global_instance_

std::weak_ptr< crash_safe_logger > kcenon::logger::safety::crash_safe_logger::global_instance_
staticprivate

Definition at line 355 of file crash_safe_logger.h.

Referenced by create(), and signal_handler().

◆ handler_mutex_

std::mutex kcenon::logger::safety::crash_safe_logger::handler_mutex_
private

Definition at line 337 of file crash_safe_logger.h.

Referenced by install_crash_handlers(), and uninstall_crash_handlers().

◆ handlers_installed_

bool kcenon::logger::safety::crash_safe_logger::handlers_installed_
private

Definition at line 338 of file crash_safe_logger.h.

Referenced by install_crash_handlers(), and uninstall_crash_handlers().

◆ logger_

std::shared_ptr<logger> kcenon::logger::safety::crash_safe_logger::logger_
private

◆ min_level_

std::atomic<log_level> kcenon::logger::safety::crash_safe_logger::min_level_
private

Definition at line 334 of file crash_safe_logger.h.

Referenced by get_min_level(), log(), log(), and set_min_level().

◆ old_sigabrt_

struct sigaction kcenon::logger::safety::crash_safe_logger::old_sigabrt_
private

Definition at line 340 of file crash_safe_logger.h.

Referenced by install_crash_handlers(), and uninstall_crash_handlers().

◆ old_sigint_

struct sigaction kcenon::logger::safety::crash_safe_logger::old_sigint_
private

Definition at line 342 of file crash_safe_logger.h.

Referenced by install_crash_handlers(), and uninstall_crash_handlers().

◆ old_sigsegv_

struct sigaction kcenon::logger::safety::crash_safe_logger::old_sigsegv_
private

Definition at line 339 of file crash_safe_logger.h.

Referenced by install_crash_handlers(), and uninstall_crash_handlers().

◆ old_sigterm_

struct sigaction kcenon::logger::safety::crash_safe_logger::old_sigterm_
private

Definition at line 341 of file crash_safe_logger.h.

Referenced by install_crash_handlers(), and uninstall_crash_handlers().

◆ stop_auto_flush_

std::atomic<bool> kcenon::logger::safety::crash_safe_logger::stop_auto_flush_
private

Definition at line 352 of file crash_safe_logger.h.

Referenced by start_auto_flush_thread(), and stop_auto_flush_thread().


The documentation for this class was generated from the following file: