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

Manager for safe signal handler installation. More...

#include <signal_manager.h>

Inheritance diagram for kcenon::logger::security::signal_manager:
Inheritance graph
Collaboration diagram for kcenon::logger::security::signal_manager:
Collaboration graph

Public Member Functions

 signal_manager ()=default
 Default constructor.
 
 ~signal_manager () override=default
 Destructor.
 
void register_logger (critical_logger_interface *log) override
 Register a logger to receive signal notifications.
 
void unregister_logger (critical_logger_interface *log) override
 Unregister a logger.
 
bool are_handlers_installed () const override
 Check if signal handlers are installed.
 
size_t logger_count () const override
 Get number of registered loggers.
 
 signal_manager (const signal_manager &)=delete
 
signal_manageroperator= (const signal_manager &)=delete
 
 signal_manager (signal_manager &&)=delete
 
signal_manageroperator= (signal_manager &&)=delete
 
- Public Member Functions inherited from kcenon::logger::security::signal_manager_interface
virtual ~signal_manager_interface ()=default
 

Private Member Functions

void install_handlers ()
 Install signal handlers.
 
void uninstall_handlers ()
 Uninstall signal handlers.
 

Static Private Member Functions

static void signal_handler (int sig)
 Signal handler (must use only signal-safe functions)
 
static void emergency_flush (critical_logger_interface *log)
 Emergency flush for a logger (signal-safe)
 

Private Attributes

std::mutex mutex_
 
std::set< critical_logger_interface * > loggers_
 
std::atomic< bool > handlers_installed_ {false}
 
void(* original_sigsegv_ )(int) = SIG_DFL
 
void(* original_sigabrt_ )(int) = SIG_DFL
 
void(* original_sigterm_ )(int) = SIG_DFL
 
void(* original_sigint_ )(int) = SIG_DFL
 

Static Private Attributes

static std::atomic< signal_manager * > current_instance_ {nullptr}
 

Detailed Description

Manager for safe signal handler installation.

Features:

  • Centralized signal handler management
  • Thread-safe logger registration
  • Uses only signal-safe functions in handlers
  • Prevents global state conflicts when multiple loggers exist
  • Implements signal_manager_interface for dependency injection
Since
2.0.0 - Converted from singleton to DI pattern

Definition at line 84 of file signal_manager.h.

Constructor & Destructor Documentation

◆ signal_manager() [1/3]

kcenon::logger::security::signal_manager::signal_manager ( )
default

Default constructor.

◆ ~signal_manager()

kcenon::logger::security::signal_manager::~signal_manager ( )
overridedefault

Destructor.

◆ signal_manager() [2/3]

kcenon::logger::security::signal_manager::signal_manager ( const signal_manager & )
delete

◆ signal_manager() [3/3]

kcenon::logger::security::signal_manager::signal_manager ( signal_manager && )
delete

Member Function Documentation

◆ are_handlers_installed()

bool kcenon::logger::security::signal_manager::are_handlers_installed ( ) const
inlineoverridevirtual

Check if signal handlers are installed.

Implements kcenon::logger::security::signal_manager_interface.

Definition at line 133 of file signal_manager.h.

133 {
134 return handlers_installed_.load();
135 }

◆ emergency_flush()

void kcenon::logger::security::signal_manager::emergency_flush ( critical_logger_interface * log)
inlinestaticprivate

Emergency flush for a logger (signal-safe)

Parameters
logLogger interface

Definition at line 344 of file signal_manager.h.

344 {
345 if (!log) {
346 return;
347 }
348
349 // Get file descriptor
350 int fd = log->get_emergency_fd();
351 if (fd < 0) {
352 return;
353 }
354
355 // Get buffer
356 const char* buffer = log->get_emergency_buffer();
357 size_t size = log->get_emergency_buffer_size();
358
359 if (buffer && size > 0) {
360 // Write using signal-safe write() syscall
361 ssize_t written = 0;
362 while (written < static_cast<ssize_t>(size)) {
363 ssize_t n = detail::safe_write(fd, buffer + written, size - written);
364 if (n <= 0) {
365 break; // Error or would block
366 }
367 written += n;
368 }
369
370 // Sync to disk (signal-safe)
372 }
373}
ssize_t safe_write(int fd, const void *buf, size_t count)
Signal-safe write wrapper (cross-platform)
int safe_fsync(int fd)
Signal-safe fsync wrapper (cross-platform)
@ size
Rotate based on file size only.

References kcenon::logger::security::critical_logger_interface::get_emergency_buffer(), kcenon::logger::security::critical_logger_interface::get_emergency_buffer_size(), kcenon::logger::security::critical_logger_interface::get_emergency_fd(), kcenon::logger::security::detail::safe_fsync(), kcenon::logger::security::detail::safe_write(), and kcenon::logger::size.

Here is the call graph for this function:

◆ install_handlers()

void kcenon::logger::security::signal_manager::install_handlers ( )
inlineprivate

Install signal handlers.

Definition at line 156 of file signal_manager.h.

156 {
157 // Set current instance for signal handler
158 current_instance_.store(this, std::memory_order_release);
159
160 // Save original handlers
161 original_sigsegv_ = std::signal(SIGSEGV, signal_handler);
162 original_sigabrt_ = std::signal(SIGABRT, signal_handler);
163 original_sigterm_ = std::signal(SIGTERM, signal_handler);
164 original_sigint_ = std::signal(SIGINT, signal_handler);
165
166 handlers_installed_.store(true);
167 }
static std::atomic< signal_manager * > current_instance_
static void signal_handler(int sig)
Signal handler (must use only signal-safe functions)

◆ logger_count()

size_t kcenon::logger::security::signal_manager::logger_count ( ) const
inlineoverridevirtual

Get number of registered loggers.

Implements kcenon::logger::security::signal_manager_interface.

Definition at line 140 of file signal_manager.h.

140 {
141 std::lock_guard lock(mutex_);
142 return loggers_.size();
143 }
std::set< critical_logger_interface * > loggers_

◆ operator=() [1/2]

signal_manager & kcenon::logger::security::signal_manager::operator= ( const signal_manager & )
delete

◆ operator=() [2/2]

signal_manager & kcenon::logger::security::signal_manager::operator= ( signal_manager && )
delete

◆ register_logger()

void kcenon::logger::security::signal_manager::register_logger ( critical_logger_interface * log)
inlineoverridevirtual

Register a logger to receive signal notifications.

Parameters
logLogger interface for emergency flushing

Signal handlers are installed when the first logger is registered.

Implements kcenon::logger::security::signal_manager_interface.

Definition at line 102 of file signal_manager.h.

102 {
103 std::lock_guard lock(mutex_);
104
105 loggers_.insert(log);
106
107 // Install handlers only on first registration
108 if (loggers_.size() == 1 && !handlers_installed_.load()) {
110 }
111 }
void install_handlers()
Install signal handlers.

◆ signal_handler()

static void kcenon::logger::security::signal_manager::signal_handler ( int sig)
inlinestaticprivate

Signal handler (must use only signal-safe functions)

Parameters
sigSignal number

Signal-safe functions (POSIX):

  • write(), fsync(), _exit()
  • Most syscalls

NOT signal-safe:

  • malloc(), free()
  • printf(), iostream
  • std::mutex (use atomic flags instead)

Definition at line 198 of file signal_manager.h.

198 {
199 // Write signal message using only signal-safe functions
200 const char* msg = nullptr;
201 size_t msg_len = 0;
202
203 switch (sig) {
204 case SIGSEGV:
205 msg = "\n[CRITICAL] SIGSEGV received - emergency flush\n";
206 msg_len = 45;
207 break;
208 case SIGABRT:
209 msg = "\n[CRITICAL] SIGABRT received - emergency flush\n";
210 msg_len = 45;
211 break;
212 case SIGTERM:
213 msg = "\n[CRITICAL] SIGTERM received - emergency flush\n";
214 msg_len = 45;
215 break;
216 case SIGINT:
217 msg = "\n[CRITICAL] SIGINT received - emergency flush\n";
218 msg_len = 44;
219 break;
220 default:
221 msg = "\n[CRITICAL] Unknown signal - emergency flush\n";
222 msg_len = 43;
223 break;
224 }
225
226 // Write to stderr (signal-safe)
227 detail::safe_write(STDERR_FILENO, msg, msg_len);
228
229 // Emergency flush for all registered loggers
230 // Note: We cannot safely lock mutex_ here (not signal-safe)
231 // Instead, we access the loggers directly (risk of race condition,
232 // but in a crash scenario, this is acceptable)
233 signal_manager* mgr = current_instance_.load(std::memory_order_acquire);
234 if (!mgr) {
235 // No instance available, nothing to flush
236 _exit(128 + sig);
237 }
238
239 // Call emergency_flush on each logger
240 // Note: This assumes the logger pointers are still valid
241 // In production, consider using a signal-safe data structure
242 for (auto* log : mgr->loggers_) {
243 if (log) {
244 emergency_flush(log);
245 }
246 }
247
248 // Call original handler (or terminate)
249 switch (sig) {
250 case SIGSEGV:
251 if (mgr->original_sigsegv_ != SIG_DFL &&
252 mgr->original_sigsegv_ != SIG_IGN) {
253 mgr->original_sigsegv_(sig);
254 } else {
255 std::signal(SIGSEGV, SIG_DFL);
256 std::raise(SIGSEGV);
257 }
258 break;
259 case SIGABRT:
260 if (mgr->original_sigabrt_ != SIG_DFL &&
261 mgr->original_sigabrt_ != SIG_IGN) {
262 mgr->original_sigabrt_(sig);
263 } else {
264 std::signal(SIGABRT, SIG_DFL);
265 std::raise(SIGABRT);
266 }
267 break;
268 case SIGTERM:
269 if (mgr->original_sigterm_ != SIG_DFL &&
270 mgr->original_sigterm_ != SIG_IGN) {
271 mgr->original_sigterm_(sig);
272 } else {
273 _exit(128 + sig);
274 }
275 break;
276 case SIGINT:
277 if (mgr->original_sigint_ != SIG_DFL &&
278 mgr->original_sigint_ != SIG_IGN) {
279 mgr->original_sigint_(sig);
280 } else {
281 _exit(128 + sig);
282 }
283 break;
284 default:
285 _exit(128 + sig);
286 }
287 }
static void emergency_flush(critical_logger_interface *log)
Emergency flush for a logger (signal-safe)
signal_manager()=default
Default constructor.

References loggers_, original_sigabrt_, original_sigint_, original_sigsegv_, and original_sigterm_.

◆ uninstall_handlers()

void kcenon::logger::security::signal_manager::uninstall_handlers ( )
inlineprivate

Uninstall signal handlers.

Definition at line 172 of file signal_manager.h.

172 {
173 // Restore original handlers
174 std::signal(SIGSEGV, original_sigsegv_);
175 std::signal(SIGABRT, original_sigabrt_);
176 std::signal(SIGTERM, original_sigterm_);
177 std::signal(SIGINT, original_sigint_);
178
179 handlers_installed_.store(false);
180
181 // Clear current instance
182 current_instance_.store(nullptr, std::memory_order_release);
183 }

◆ unregister_logger()

void kcenon::logger::security::signal_manager::unregister_logger ( critical_logger_interface * log)
inlineoverridevirtual

Unregister a logger.

Parameters
logLogger to unregister

Signal handlers are removed when the last logger is unregistered.

Implements kcenon::logger::security::signal_manager_interface.

Definition at line 119 of file signal_manager.h.

119 {
120 std::lock_guard lock(mutex_);
121
122 loggers_.erase(log);
123
124 // Remove handlers when last logger is unregistered
125 if (loggers_.empty() && handlers_installed_.load()) {
127 }
128 }
void uninstall_handlers()
Uninstall signal handlers.

Member Data Documentation

◆ current_instance_

std::atomic< signal_manager * > kcenon::logger::security::signal_manager::current_instance_ {nullptr}
staticprivate

Current instance for signal handler (static due to C signal API limitation) Note: Only one instance can handle signals at a time

Definition at line 297 of file signal_manager.h.

◆ handlers_installed_

std::atomic<bool> kcenon::logger::security::signal_manager::handlers_installed_ {false}
private

Definition at line 301 of file signal_manager.h.

301{false};

◆ loggers_

std::set<critical_logger_interface*> kcenon::logger::security::signal_manager::loggers_
private

Definition at line 300 of file signal_manager.h.

Referenced by signal_handler().

◆ mutex_

std::mutex kcenon::logger::security::signal_manager::mutex_
mutableprivate

Definition at line 299 of file signal_manager.h.

◆ original_sigabrt_

void(* kcenon::logger::security::signal_manager::original_sigabrt_) (int) = SIG_DFL
private

Definition at line 305 of file signal_manager.h.

Referenced by signal_handler().

◆ original_sigint_

void(* kcenon::logger::security::signal_manager::original_sigint_) (int) = SIG_DFL
private

Definition at line 307 of file signal_manager.h.

Referenced by signal_handler().

◆ original_sigsegv_

void(* kcenon::logger::security::signal_manager::original_sigsegv_) (int) = SIG_DFL
private

Definition at line 304 of file signal_manager.h.

Referenced by signal_handler().

◆ original_sigterm_

void(* kcenon::logger::security::signal_manager::original_sigterm_) (int) = SIG_DFL
private

Definition at line 306 of file signal_manager.h.

Referenced by signal_handler().


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