Skip to content

Error Handling Strategy: Aegis

High-performance applications must handle failures without stalling the primary pipeline or crashing unpredictably. This document defines the error handling and logging strategy for Aegis.


1. Classification of Failures

1.1 Recoverable Errors

Recoverable errors are handled gracefully without aborting execution.

  • Malformed Packet Frames: If a packet fails parsing checks (e.g. invalid IP version, TCP length exceeds raw buffer size, corrupt headers), the packet parser aborts decoding immediately, increments parse_errors_ in the metrics block, and releases the buffer frame to the pool.
  • Incomplete Handshakes: Fragmented TLS Client Hello packets that cannot be parsed are kept in the flow scratch buffer. If the flow times out before reassembly completes, the scratch buffer is cleared.
  • Invalid Rules Configuration: Loading invalid domains or subnets logs a warning message. The engine ignores the corrupt rule and continues processing packets using the previous rule set.
  • Inactivity Flow Expiry: Connections that do not send packets within the timeout window are quietly evicted by the sweeper thread.

1.2 Fatal Errors

Fatal errors cause immediate, controlled system shutdown.

  • Memory Pool Exhaustion on Startup: Failure to allocate the contiguous packet block array at startup aborts the application with a std::runtime_error.
  • PCAP File Access Failure: If the specified capture file does not exist or lacks read permissions, Aegis logs an error and returns exit code 1.
  • Core Pinning Failure (Strict Mode): If a thread affinity mask cannot be set and the configuration demands strict core isolation, Aegis aborts execution to prevent noisy neighbor performance issues.

2. Queue Overflow & Backpressure

Since our lock-free SPSC queues are bounded, thread speeds must coordinate to prevent packet loss.

  • Ingestion Queue Full: If the ingestion SPSC queue is full, the reader thread yields execution using std::this_thread::yield() or spins for a fixed cycle count before retrying. This slows ingestion to match worker throughput.
  • Worker-to-Writer SPSC Queue Full: If a worker's Output queue is full, the worker blocks (spins) or drops the frame (if live capture mode) and increments the dropped_packets metric.

3. Hot-Path Logging Policy

  • Rule: Writing directly to standard output (std::cout, std::cerr) or files on the packet hot path is prohibited, as disk/console IO takes milliseconds and blocks execution.
  • Non-Blocking Logs: Errors on the hot path are recorded by incrementing thread-local atomic counters. A separate, low-priority background logging thread polls these metrics periodically and writes messages to stdout or logs.
  • Initialization/Shutdown Logs: Standard blocking logging is permitted only during startup, config loading, and shutdown phases.