Skip to content

Fatal Handling

Eduard Mishkurov edited this page Jun 19, 2026 · 2 revisions

Fatal Handling and Critical Logs

LogmeC writes a LEVEL_CRITICAL record. By default it does not terminate the process.

This is intentional. Existing projects and tests may use critical messages as severe diagnostics without expecting abort() or std::terminate() to be called. Termination is a policy decision, and logme lets the application choose that policy explicitly.

Fatal handler

A process can install a fatal handler on the global logger:

Logme::Instance->SetFatalHandler([]()
{
  std::abort();
});

or:

Logme::Instance->SetFatalHandler([]()
{
  std::terminate();
});

The handler is called after a LEVEL_CRITICAL record is written. If no handler is installed, LogmeC behaves like any other log level and only writes the critical record.

The handler can be reset:

Logme::Instance->ResetFatalHandler();

Flush before termination

When a fatal handler is installed, logme calls:

Logme::Instance->FlushAll();

before invoking the handler.

This matters for long-running services and asynchronous file logging. A critical message is often the last useful diagnostic before a crash or forced shutdown. FlushAll() gives backends and managers a chance to write pending records before the process terminates.

FlushAll() is also available as a normal public API. It is useful when the application has its own shutdown, signal, or crash handling policy.

Example:

static void HandleSigabrt(int signum)
{
  ::signal(signum, SIG_DFL);

  LogmeE("SIGABRT received. Terminating the program...");
  Logme::Instance->FlushAll();

  ::abort();
}

logme does not install signal handlers by itself. Signal policy belongs to the application.

Recursion protection

Fatal handling is protected against recursion. If a fatal handler writes another critical message, logme will not start a second nested fatal-handling path.

This allows handlers to write final diagnostics without creating infinite recursion. The critical record is still written; the repeated fatal callback is suppressed.

Relation to glog-style CHECK and FATAL

The glog compatibility macros use this mechanism.

LOG(FATAL), CHECK(...), CHECK_EQ(...), and PCHECK(...) write through LogmeC. Whether the process terminates depends on the installed fatal handler.

This gives two useful modes:

// Compatibility mode with glog-like termination.
Logme::Instance->SetFatalHandler([]()
{
  std::abort();
});

or:

// Test or diagnostic mode: critical logs are recorded, but the process continues.
Logme::Instance->ResetFatalHandler();

That separation is deliberate. LEVEL_CRITICAL describes the severity of the record. The fatal handler describes what the application wants to do after such a record.

C API

The C API exposes global flushing:

LogmeFlushAll();

Fatal handler configuration is C++ API only.

Clone this wiki locally