25 #define STDERR_FILENO 2
27 using ssize_t = intptr_t;
46inline ssize_t
safe_write(
int fd,
const void* buf,
size_t count) {
48 return _write(fd, buf,
static_cast<unsigned int>(count));
50 return ::write(fd, buf, count);
103 std::lock_guard lock(mutex_);
105 loggers_.insert(log);
108 if (loggers_.size() == 1 && !handlers_installed_.load()) {
120 std::lock_guard lock(mutex_);
125 if (loggers_.empty() && handlers_installed_.load()) {
126 uninstall_handlers();
134 return handlers_installed_.load();
141 std::lock_guard lock(mutex_);
142 return loggers_.size();
158 current_instance_.store(
this, std::memory_order_release);
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);
166 handlers_installed_.store(
true);
174 std::signal(SIGSEGV, original_sigsegv_);
175 std::signal(SIGABRT, original_sigabrt_);
176 std::signal(SIGTERM, original_sigterm_);
177 std::signal(SIGINT, original_sigint_);
179 handlers_installed_.store(
false);
182 current_instance_.store(
nullptr, std::memory_order_release);
200 const char* msg =
nullptr;
205 msg =
"\n[CRITICAL] SIGSEGV received - emergency flush\n";
209 msg =
"\n[CRITICAL] SIGABRT received - emergency flush\n";
213 msg =
"\n[CRITICAL] SIGTERM received - emergency flush\n";
217 msg =
"\n[CRITICAL] SIGINT received - emergency flush\n";
221 msg =
"\n[CRITICAL] Unknown signal - emergency flush\n";
227 detail::safe_write(STDERR_FILENO, msg, msg_len);
233 signal_manager* mgr = current_instance_.load(std::memory_order_acquire);
244 emergency_flush(log);
255 std::signal(SIGSEGV, SIG_DFL);
264 std::signal(SIGABRT, SIG_DFL);
301 std::atomic<bool> handlers_installed_{
false};
304 void (*original_sigsegv_)(int) = SIG_DFL;
305 void (*original_sigabrt_)(int) = SIG_DFL;
306 void (*original_sigterm_)(int) = SIG_DFL;
307 void (*original_sigint_)(int) = SIG_DFL;
359 if (buffer &&
size > 0) {
362 while (written <
static_cast<ssize_t
>(
size)) {
Interface for loggers that support emergency flushing.
virtual ~critical_logger_interface()=default
virtual int get_emergency_fd() const =0
Get file descriptor for emergency writing.
virtual const char * get_emergency_buffer() const =0
Get emergency buffer pointer.
virtual size_t get_emergency_buffer_size() const =0
Get emergency buffer size.
Interface for signal handler management.
Manager for safe signal handler installation.
void register_logger(critical_logger_interface *log) override
Register a logger to receive signal notifications.
std::set< critical_logger_interface * > loggers_
void(* original_sigsegv_)(int)
signal_manager(signal_manager &&)=delete
void(* original_sigterm_)(int)
void(* original_sigint_)(int)
void install_handlers()
Install signal handlers.
signal_manager(const signal_manager &)=delete
void uninstall_handlers()
Uninstall signal handlers.
static std::atomic< signal_manager * > current_instance_
void(* original_sigabrt_)(int)
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)
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() override=default
Destructor.
signal_manager & operator=(signal_manager &&)=delete
signal_manager()=default
Default constructor.
signal_manager & operator=(const signal_manager &)=delete
DLL export/import macros for logger_system shared library support.
#define LOGGER_SYSTEM_API
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.
Interface for signal handler management.