ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches

⚠️ Thread-Local Error Number System with Context More...

Files

file  asciichat_errno.c
 🚨 Custom error code system with formatted messages, thread-local storage, and errno mapping
 
file  asciichat_errno.h
 ⚠️‼️ Comprehensive thread-local error context system for ascii-chat
 

Data Structures

struct  backtrace_t
 
struct  asciichat_error_context_t
 Error context structure. More...
 
struct  asciichat_error_stats_t
 Error statistics structure. More...
 

Macros

#define SET_ERRNO(code, context_msg, ...)
 Set error code with custom context message and log it, returning the error code.
 
#define SET_ERRNO_SYS(code, context_msg, ...)
 Set error code with custom message and system error context, returning the error code.
 
#define HAS_ERRNO(var)   asciichat_has_errno(var)
 Check if an error occurred and get full context.
 
#define CLEAR_ERRNO()   asciichat_clear_errno()
 Clear the current error state.
 
#define GET_ERRNO()   asciichat_get_errno()
 Get current error code (0 if no error)
 

Functions

void asciichat_set_errno (asciichat_error_t code, const char *file, int line, const char *function, const char *context_message)
 Set error code with basic context.
 
void asciichat_set_errno_with_message (asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
 Set error code with formatted message.
 
void asciichat_set_errno_with_system_error (asciichat_error_t code, const char *file, int line, const char *function, int sys_errno)
 Set error code with system error (errno)
 
void asciichat_set_errno_with_system_error_and_message (asciichat_error_t code, const char *file, int line, const char *function, int sys_errno, const char *format,...)
 Set error code with system error and formatted message.
 
void asciichat_set_errno_with_wsa_error (asciichat_error_t code, const char *file, int line, const char *function, int wsa_error)
 Set error code with Windows socket error (WSA error)
 
bool asciichat_has_errno (asciichat_error_context_t *context)
 Check if error occurred and get full context.
 
bool asciichat_has_wsa_error (void)
 Check if current error has WSA error code.
 
void asciichat_clear_errno (void)
 Clear the current error state.
 
asciichat_error_t asciichat_get_errno (void)
 Get current error code.
 
void asciichat_fatal_with_context (asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
 Exit with error code and context (used by FATAL macro)
 
void asciichat_print_error_context (const asciichat_error_context_t *context)
 Print full error context to stderr.
 
void asciichat_error_stats_init (void)
 Initialize error statistics system.
 
void asciichat_error_stats_record (asciichat_error_t code)
 Record an error in statistics.
 
void asciichat_error_stats_print (void)
 Print error statistics to stderr.
 
void asciichat_error_stats_reset (void)
 Reset all error statistics to zero.
 
asciichat_error_stats_t asciichat_error_stats_get (void)
 Get current error statistics.
 
asciichat_error_t asciichat_get_thread_error (int thread_id)
 Get error code for a specific thread.
 
void asciichat_set_thread_error (int thread_id, asciichat_error_t code)
 Set error code for a specific thread.
 
void asciichat_clear_thread_error (int thread_id)
 Clear error code for a specific thread.
 
void asciichat_errno_suppress (bool suppress)
 Suppress error logging and reporting.
 
void asciichat_errno_destroy (void)
 Cleanup error system resources.
 

Variables

__thread asciichat_error_context_t asciichat_errno_context
 Thread-local error context storage.
 
__thread asciichat_error_t asciichat_errno
 Thread-local current error code.
 

Detailed Description

⚠️ Thread-Local Error Number System with Context

Overview

This header defines ascii-chat's centralized error handling system: a thread-local error number system with full context capture including location information, stack traces (debug builds), and system error integration. Rather than the limited errno semantics of standard C (which loses context), this system captures the full error story: where it happened, why it happened, and what the calling code was trying to do.

This is NOT a cosmetic improvement. Error handling is one of the most critical parts of ascii-chat. With 2,880+ SET_ERRNO calls throughout 250+ library files and 50+ source files, nearly every significant operation in the codebase uses this system. The densest users are network (91 calls in packet parsing alone), crypto (86+ in SSH key parsing, 86+ in crypto context, 68+ in handshakes), and utilities (53+ in IP parsing).

Why This Matters

Good error messages save hours of debugging. Without context:

With this system:

Core Architecture

Thread-Local Error Context (asciichat_error_context_t):

Library Interface (lib/ code):

Application Interface (src/ code):

Usage Patterns (From Real Code)

Pattern 1: Input Validation (Network Packet Parsing)

~1000+ locations - the most common pattern

if (!header || !pkt_type) {
return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid parameters: header=%p, pkt_type=%p", header, pkt_type);
}
if (magic != PACKET_MAGIC) {
return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid packet magic: 0x%x (expected 0x%x)",
magic, PACKET_MAGIC);
}
if (len > MAX_PACKET_SIZE) {
return SET_ERRNO(ERROR_NETWORK_SIZE, "Packet too large: %u > %d", len, MAX_PACKET_SIZE);
}
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it, returning the error code.
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:81
@ ERROR_NETWORK_SIZE
Definition error_codes.h:82
@ ERROR_INVALID_PARAM
#define MAX_PACKET_SIZE
Maximum packet size (5MB)
Definition packet.h:115
#define PACKET_MAGIC
Packet magic number (alias for MAGIC_PACKET_VALID)
Definition packet.h:255

Pattern 2: Memory Allocation Failure (Crypto Operations)

~400+ locations

uint8_t *key = SAFE_MALLOC(key_size, uint8_t *);
if (!key) {
return SET_ERRNO(ERROR_MEMORY, "Failed to allocate %zu bytes for ephemeral key", key_size);
}
#define SAFE_MALLOC(size, cast)
Definition common.h:264
unsigned char uint8_t
Definition common.h:56
@ ERROR_MEMORY
Definition error_codes.h:56

Pattern 3: System Call Failure with errno (File I/O, Networking)

~166 locations - use SET_ERRNO_SYS to capture both errno and context

int fd = open(path, O_RDONLY);
if (fd < 0) {
return SET_ERRNO_SYS(ERROR_CONFIG, "Failed to open config: %s", path);
// Logs: "Failed to open config: /etc/ascii-chat.conf (errno: 2 - No such file)"
}
#define SET_ERRNO_SYS(code, context_msg,...)
Set error code with custom message and system error context, returning the error code.
@ ERROR_CONFIG
Definition error_codes.h:57

Pattern 4: Error Context Propagation

~50+ locations - deepest call checks error without overwriting

// In crypto_perform_handshake() - deep function
asciichat_error_t result = validate_server_signature(sig_data, server_key);
if (result != ASCIICHAT_OK) {
return result; // Propagates original error context up the call stack
}
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
@ ASCIICHAT_OK
Definition error_codes.h:51

Pattern 5: Application-Level Error Handling

~30 locations - entry points check errors after library calls

// In src/client/main.c
if (HAS_ERRNO(&err_ctx)) {
FATAL(err_ctx.code, "Connection failed: %s at %s:%d",
err_ctx.context_message, err_ctx.file, err_ctx.line);
}
#define FATAL(code,...)
Exit with error code and custom message, with stack trace in debug builds.
Definition common.h:158
#define HAS_ERRNO(var)
Check if an error occurred and get full context.
Error context structure.
char * context_message
Optional custom message (dynamically allocated, owned by system)
const char * file
Source file where error occurred (NULL in release builds)
int line
Line number where error occurred (0 in release builds)
asciichat_error_t code
Error code (asciichat_error_t enum value)

Thread Safety Guarantee

Each thread has completely independent error state via __thread storage:

Context Capture Details

In Release Builds (NDEBUG):

In Debug Builds:

Error Statistics (Monitoring & Diagnostics)

The system tracks cumulative error counts per error code across all threads:

printf("Total errors seen: %llu\\n", stats.total_errors);
printf("Network errors: %llu\\n", stats.error_counts[ERROR_NETWORK]);
printf("Crypto errors: %llu\\n", stats.error_counts[ERROR_CRYPTO]);
asciichat_error_stats_t stats
asciichat_error_stats_t asciichat_error_stats_get(void)
Get current error statistics.
@ ERROR_NETWORK
Definition error_codes.h:77
@ ERROR_CRYPTO
Definition error_codes.h:96
Error statistics structure.
uint64_t error_counts[256]
Count for each error code (256 possible error codes)
uint64_t total_errors
Total number of errors recorded (sum of all error_counts)

Useful for:

Common Error Codes (From error_codes.h)

Debugging with Error Context

In GDB:

$1 = {code = ERROR_CRYPTO, file = "lib/crypto/handshake/client.c", line = 892,
function = "handle_key_exchange_reply", context_message = "Signature verification failed",
timestamp = 1730851234567890, ...}
__thread asciichat_error_context_t asciichat_errno_context
Thread-local error context storage.
#define print(s)
Print string to stdout.
Definition ascii.h:488

In Running Program (if dumped by FATAL):

[ERROR] ERROR_CRYPTO: Signature verification failed
Location: lib/crypto/handshake/client.c:892 in handle_key_exchange_reply()
Timestamp: 2025-10-06 14:07:14.567890 UTC
System error: 0 (success)
Stack trace (11 frames):
[0] handle_key_exchange_reply (lib/crypto/handshake/client.c:892)
[1] crypto_perform_handshake (lib/crypto/crypto.c:156)
[2] connection_authenticate (src/client/connection.c:289)
... (8 more frames)
Note
Use SET_ERRNO() in library code. Macros auto-capture file/line/function.
Use HAS_ERRNO() in application code to check errors after library calls.
Stack traces are only captured in debug builds with ENABLE_ERRNO_BACKTRACES.
Thread-local storage ensures thread safety automatically (no synchronization).
This is the error handling backbone of ascii-chat. Understand it well.
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
October 2025

asciichat_errno

Overview

The Error Handling System provides comprehensive error tracking and reporting for ascii-chat. It uses typed error codes, error context capture, and thread-local storage for safe multi-threaded error handling.

Implementation: lib/asciichat_errno.h

Key Features:

  • Typed error codes via asciichat_error_t enum
  • Thread-local error context storage
  • Automatic file/line/function capture
  • System error integration (errno capture)
  • Error context stack traces (debug builds)
  • Comprehensive error messages with context

Architecture

Error Code System:

  • All functions return asciichat_error_t instead of int
  • ASCIICHAT_OK (0) indicates success
  • Negative values indicate specific error types
  • Error codes are categorized by subsystem

Thread-Local Storage:

  • Each thread has its own error context
  • No cross-thread error contamination
  • Safe for concurrent error handling

Error Context Capture:

  • File name and line number where error occurred
  • Function name where error was set
  • Custom error message with printf-style formatting
  • System errno value (when applicable)
  • Stack trace (debug builds only)

Usage Patterns

Setting Errors

SET_ERRNO Macro (preferred):

// Set error with custom message
if (socket_fd < 0) {
return SET_ERRNO(ERROR_NETWORK_SOCKET, "Failed to create socket");
}
// Set error with formatted message
if (bind(sockfd, &addr, sizeof(addr)) < 0) {
return SET_ERRNO(ERROR_NETWORK_BIND, "Cannot bind to port %d", port);
}
@ ERROR_NETWORK_BIND
Definition error_codes.h:78

SET_ERRNO_SYS Macro (captures system errno):

// Capture both error code and system errno
int fd = open(path, O_RDONLY);
if (fd < 0) {
return SET_ERRNO_SYS(ERROR_CONFIG, "Failed to open config: %s", path);
}

Checking Errors

Check for Error:

if (HAS_ERRNO(&err_ctx)) {
log_error("Error: %s", err_ctx.context_message);
log_error(" at %s:%d in %s()", err_ctx.file, err_ctx.line, err_ctx.function);
}
#define log_error(...)
Log an ERROR message.
Definition log/log.h:587
const char * function
Function name where error occurred (NULL in release builds)

Get Current Error Code:

asciichat_error_t current_error = GET_ERRNO();
if (current_error != ASCIICHAT_OK) {
// Handle error
}
#define GET_ERRNO()
Get current error code (0 if no error)

Clear Error State:

CLEAR_ERRNO(); // Reset error state for this thread
#define CLEAR_ERRNO()
Clear the current error state.

Debug Output

Print Error Context (debug builds only):

if (HAS_ERRNO(&err_ctx)) {
PRINT_ERRNO_CONTEXT(&err_ctx); // Prints full context including stack trace
}
#define PRINT_ERRNO_CONTEXT(context)

Error Code Categories

General Errors:

  • ASCIICHAT_OK (0) - Success
  • ERROR_UNKNOWN (-1) - Unknown error
  • ERROR_INVALID_PARAM (-2) - Invalid parameter
  • ERROR_OUT_OF_MEMORY (-3) - Memory allocation failed

Network Errors:

  • ERROR_NETWORK_SOCKET - Socket creation failed
  • ERROR_NETWORK_BIND - Socket bind failed
  • ERROR_NETWORK_LISTEN - Socket listen failed
  • ERROR_NETWORK_CONNECT - Connection failed
  • ERROR_NETWORK_SEND - Send operation failed
  • ERROR_NETWORK_RECV - Receive operation failed

Crypto Errors:

  • ERROR_CRYPTO_INIT - Crypto initialization failed
  • ERROR_CRYPTO_KEY - Key loading/parsing failed
  • ERROR_CRYPTO_HANDSHAKE - Handshake failed
  • ERROR_CRYPTO_ENCRYPT - Encryption failed
  • ERROR_CRYPTO_DECRYPT - Decryption failed

Platform Errors:

  • ERROR_PLATFORM_THREAD - Thread operation failed
  • ERROR_PLATFORM_MUTEX - Mutex operation failed
  • ERROR_PLATFORM_SOCKET - Platform-specific socket error

Configuration Errors:

  • ERROR_CONFIG - Configuration loading failed
  • ERROR_CONFIG_PARSE - Configuration parsing failed
  • ERROR_CONFIG_INVALID - Invalid configuration value

Integration with Logging

Automatic Logging:

  • SET_ERRNO() automatically logs errors at ERROR level
  • SET_ERRNO_SYS() logs with system error details
  • Error messages include context automatically

Example Integration:

asciichat_error_t process_client(client_t *client) {
if (!client) {
return SET_ERRNO(ERROR_INVALID_PARAM, "Client is NULL");
// Automatically logged: "ERROR: Client is NULL"
}
int result = some_operation();
if (result < 0) {
return SET_ERRNO_SYS(ERROR_OPERATION_FAILED, "Operation failed");
// Automatically logged with errno details
}
return ASCIICHAT_OK;
}

Best Practices

DO:

  • Always use asciichat_error_t for return types
  • Use SET_ERRNO() for all error conditions
  • Use SET_ERRNO_SYS() when capturing system errors
  • Provide descriptive error messages
  • Check return values and propagate errors

DON'T:

  • Don't use int return values with -1 for errors
  • Don't ignore return values
  • Don't use generic error messages
  • Don't access errno directly (use SET_ERRNO_SYS)
  • Don't forget to check errors from called functions

Thread Safety

Thread-Local Storage:

  • Each thread maintains its own error context
  • No locks needed for error operations
  • Safe for concurrent error handling
  • Thread ID captured in error context

Example Multi-threaded Usage:

void* worker_thread(void *arg) {
// This thread's error context is independent
asciichat_error_t err = do_work();
if (err != ASCIICHAT_OK) {
if (HAS_ERRNO(&ctx)) {
log_error("Worker failed: %s", ctx.context_message);
}
}
return NULL;
}
See also
asciichat_errno.h
logging.h

Macro Definition Documentation

◆ CLEAR_ERRNO

#define CLEAR_ERRNO ( )    asciichat_clear_errno()

#include <asciichat_errno.h>

Clear the current error state.

Definition at line 375 of file asciichat_errno.h.

◆ GET_ERRNO

#define GET_ERRNO ( )    asciichat_get_errno()

#include <asciichat_errno.h>

Get current error code (0 if no error)

Definition at line 380 of file asciichat_errno.h.

◆ HAS_ERRNO

#define HAS_ERRNO (   var)    asciichat_has_errno(var)

#include <asciichat_errno.h>

Check if an error occurred and get full context.

Parameters
varVariable to store error context

Usage in src/ code: asciichat_error_context_t err_ctx; if (HAS_ERRNO(&err_ctx)) { FATAL(err_ctx.code, "Library error occurred"); }

Definition at line 370 of file asciichat_errno.h.

◆ SET_ERRNO

#define SET_ERRNO (   code,
  context_msg,
  ... 
)

#include <asciichat_errno.h>

Value:
(asciichat_set_errno_with_message(code, __FILE__, __LINE__, __func__, context_msg, ##__VA_ARGS__), \
log_error("SET_ERRNO: " context_msg " (code: %d, meaning: %s)", ##__VA_ARGS__, code, asciichat_error_string(code)), \
(code))
void asciichat_set_errno_with_message(asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
Set error code with formatted message.

Set error code with custom context message and log it, returning the error code.

Parameters
codeError code to set
context_msgCustom message explaining the error

Usage in lib/ code: if (bind(sockfd, ...) < 0) { return SET_ERRNO(ERROR_NETWORK_BIND, "Cannot bind to port %d", port); }

Definition at line 316 of file asciichat_errno.h.

318 : " context_msg " (code: %d, meaning: %s)", ##__VA_ARGS__, code, asciichat_error_string(code)), \
319 (code))

◆ SET_ERRNO_SYS

#define SET_ERRNO_SYS (   code,
  context_msg,
  ... 
)

#include <asciichat_errno.h>

Value:
context_msg, ##__VA_ARGS__), \
log_error("SETERRNO_SYS: " context_msg " (code: %d - %s, system error: %d - %s)", ##__VA_ARGS__, code, \
asciichat_error_string(code), platform_get_last_error(), platform_strerror(platform_get_last_error())), \
(code))
void asciichat_set_errno_with_system_error_and_message(asciichat_error_t code, const char *file, int line, const char *function, int sys_errno, const char *format,...)
Set error code with system error and formatted message.
int platform_get_last_error(void)
Get the last system error code.
Definition util.c:89
const char * platform_strerror(int errnum)
Get human-readable error message for a system error code.
Definition wasm/system.c:46

Set error code with custom message and system error context, returning the error code.

Parameters
codeError code to set
context_msgCustom message explaining the error

Usage in lib/ code: if (open(file, O_RDONLY) < 0) { return SET_ERRNO_SYS(ERROR_CONFIG, "Failed to open config file: %s", path); }

Definition at line 340 of file asciichat_errno.h.

343 : " context_msg " (code: %d - %s, system error: %d - %s)", ##__VA_ARGS__, code, \
344 asciichat_error_string(code), platform_get_last_error(), platform_strerror(platform_get_last_error())), \
345 (code))

Function Documentation

◆ asciichat_clear_errno()

void asciichat_clear_errno ( void  )

#include <asciichat_errno.h>

Clear the current error state.

Clears the thread-local error state, resetting error code to ASCIICHAT_OK and freeing any associated context message. This is the low-level function used by CLEAR_ERRNO() macro.

Note
Error context structure is reset to default state.
Any context message is freed automatically.
Thread-safe: Uses thread-local storage.
Warning
Use CLEAR_ERRNO() macro instead of calling this directly.

Definition at line 233 of file asciichat_errno.c.

233 {
237 }
238
240
247
248 /* Clear platform-specific error state */
250}
void backtrace_t_free(backtrace_t *bt)
Free backtrace symbols.
#define SAFE_FREE(ptr)
Definition common.h:376
void platform_clear_error_state(void)
Definition util.c:69
int wsa_error
Windows socket error code (if applicable, 0 otherwise)
int system_errno
System errno value (if applicable, 0 otherwise)
bool has_system_error
True if system_errno is valid.
bool has_wsa_error
True if wsa_error is valid.
backtrace_t backtrace
Stack trace (debug builds only)

References asciichat_errno_context, ASCIICHAT_OK, asciichat_error_context_t::backtrace, backtrace_t_free(), asciichat_error_context_t::code, asciichat_error_context_t::context_message, asciichat_error_context_t::has_system_error, asciichat_error_context_t::has_wsa_error, platform_clear_error_state(), SAFE_FREE, asciichat_error_context_t::system_errno, and asciichat_error_context_t::wsa_error.

◆ asciichat_clear_thread_error()

void asciichat_clear_thread_error ( int  thread_id)

#include <asciichat_errno.h>

Clear error code for a specific thread.

Parameters
thread_idThread ID to clear error for

Clears the error code for a specific thread, resetting it to ASCIICHAT_OK.

Note
Thread ID must be valid (positive integer).

Definition at line 486 of file asciichat_errno.c.

486 {
487 for (int i = 0; i < MAX_THREAD_ERRORS; i++) {
488 if (thread_errors[i].valid && thread_errors[i].thread_id == thread_id) {
489 thread_errors[i].valid = false;
490 break;
491 }
492 }
493}
#define MAX_THREAD_ERRORS
bool valid
int thread_id

References MAX_THREAD_ERRORS, thread_id, and valid.

◆ asciichat_errno_destroy()

void asciichat_errno_destroy ( void  )

#include <asciichat_errno.h>

Cleanup error system resources.

Cleans up error system resources including statistics and thread error storage. Should be called at application shutdown after all error handling is complete.

Note
Safe to call multiple times (no-op after first call).
All error statistics and context messages are freed.

Definition at line 504 of file asciichat_errno.c.

504 {
506
509 }
510
511 // Reset the context to a clean state
514
515 // Suppress any further error context allocation to prevent cleanup-phase leaks
516 // This prevents other atexit() functions from allocating new contexts after we've cleaned up
517 g_suppress_error_context = true;
518}

References asciichat_errno_context, ASCIICHAT_OK, asciichat_error_context_t::backtrace, backtrace_t_free(), asciichat_error_context_t::code, asciichat_error_context_t::context_message, and SAFE_FREE.

Referenced by asciichat_shared_destroy(), client_audio_render_thread(), client_receive_thread(), client_send_thread_func(), client_video_render_thread(), and stats_logger_thread().

◆ asciichat_errno_suppress()

void asciichat_errno_suppress ( bool  suppress)

#include <asciichat_errno.h>

Suppress error logging and reporting.

Parameters
suppressIf true, suppress error logging; if false, enable logging

Controls whether errors are automatically logged when set. When suppressed, errors are still set in thread-local storage but logging is disabled. Useful for testing or when error logging would be too verbose.

Note
Suppression only affects automatic logging, not manual error checking.
Errors can still be checked using HAS_ERRNO() and GET_ERRNO().

Definition at line 500 of file asciichat_errno.c.

500 {
501 g_suppress_error_context = suppress;
502}

◆ asciichat_error_stats_get()

asciichat_error_stats_t asciichat_error_stats_get ( void  )

#include <asciichat_errno.h>

Get current error statistics.

Returns
Current error statistics structure (copy)

Retrieves a copy of the current error statistics. Returns all statistics including per-error-code counts, total errors, and last error information.

Note
Returns a copy of statistics (caller can modify without affecting internal state).
Thread-safe: Can be called from any thread.

Definition at line 440 of file asciichat_errno.c.

440 {
441 if (!lifecycle_is_initialized(&g_error_stats.lifecycle)) {
442 lifecycle_init(&g_error_stats.lifecycle, "error_stats");
443 }
444
445 mutex_lock(&g_error_stats.mutex);
446 asciichat_error_stats_t result = g_error_stats.stats;
447 mutex_unlock(&g_error_stats.mutex);
448
449 return result;
450}
#define mutex_lock(mutex)
Lock a mutex (with debug tracking in debug builds)
#define mutex_unlock(mutex)
Unlock a mutex (with debug tracking in debug builds)
bool lifecycle_is_initialized(const lifecycle_t *lc)
Definition lifecycle.c:155
bool lifecycle_init(lifecycle_t *lc, const char *name)
Definition lifecycle.c:26

References lifecycle_init(), lifecycle_is_initialized(), mutex_lock, and mutex_unlock.

◆ asciichat_error_stats_init()

void asciichat_error_stats_init ( void  )

#include <asciichat_errno.h>

Initialize error statistics system.

Initializes the error statistics tracking system. Must be called before recording any error statistics. Statistics are initialized to zero.

Note
Idempotent: Safe to call multiple times (no-op after first call).
Thread-safe: Can be called from any thread.

Definition at line 365 of file asciichat_errno.c.

365 {
366 if (lifecycle_init(&g_error_stats.lifecycle, "error_stats")) {
367 memset(&g_error_stats.stats, 0, sizeof(g_error_stats.stats));
368 }
369}

References lifecycle_init().

◆ asciichat_error_stats_print()

void asciichat_error_stats_print ( void  )

#include <asciichat_errno.h>

Print error statistics to stderr.

Prints comprehensive error statistics including per-error-code counts, total errors, and last error information. Useful for periodic monitoring and debugging.

Note
Statistics are formatted and printed at INFO level.
Requires statistics system to be initialized.

Definition at line 391 of file asciichat_errno.c.

391 {
392 if (!lifecycle_is_initialized(&g_error_stats.lifecycle)) {
393 log_plain("No errors recorded.\n");
394 return;
395 }
396
397 mutex_lock(&g_error_stats.mutex);
398
399 if (g_error_stats.stats.total_errors == 0) {
400 mutex_unlock(&g_error_stats.mutex);
401 log_plain("No errors recorded.\n");
402 return;
403 }
404
405 // Copy stats to local variable to minimize lock hold time
406 asciichat_error_stats_t local_stats = g_error_stats.stats;
407 mutex_unlock(&g_error_stats.mutex);
408
409 log_plain("\n=== ascii-chat Error Statistics ===\n");
410 log_plain("Total errors: %llu\n", (unsigned long long)local_stats.total_errors);
411
412 if (local_stats.last_error_time > 0) {
413 time_t sec = (time_t)(local_stats.last_error_time / NS_PER_MS_INT);
414 struct tm tm_info;
415 if (platform_localtime(&sec, &tm_info) == ASCIICHAT_OK) {
416 char time_str[64];
417 strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_info);
418 log_plain("Last error: %s (code %d)\n", time_str, (int)local_stats.last_error_code);
419 }
420 }
421
422 log_plain("\nError breakdown:\n");
423 for (int i = 0; i < 256; i++) {
424 if (local_stats.error_counts[i] > 0) {
425 log_plain(" %3d (%s): %llu\n", i, asciichat_error_string((asciichat_error_t)i),
426 (unsigned long long)local_stats.error_counts[i]);
427 }
428 }
429 log_plain("\n");
430}
#define log_plain(...)
Plain logging - writes to both log file and stderr without timestamps or log levels.
Definition log/log.h:618
#define NS_PER_MS_INT
Definition time.h:156
asciichat_error_t platform_localtime(const time_t *timer, struct tm *result)
Platform-safe localtime wrapper.
Definition util.c:50
uint64_t last_error_time
Timestamp of last error (microseconds since epoch)
asciichat_error_t last_error_code
Error code of last error recorded.

References ASCIICHAT_OK, asciichat_error_stats_t::error_counts, asciichat_error_stats_t::last_error_code, asciichat_error_stats_t::last_error_time, lifecycle_is_initialized(), log_plain, mutex_lock, mutex_unlock, NS_PER_MS_INT, platform_localtime(), and asciichat_error_stats_t::total_errors.

Referenced by stats_logger_thread().

◆ asciichat_error_stats_record()

void asciichat_error_stats_record ( asciichat_error_t  code)

#include <asciichat_errno.h>

Record an error in statistics.

Parameters
codeError code to record (asciichat_error_t)

Records an error occurrence in the statistics system. Updates per-error-code count, total error count, and last error information.

Note
Thread-safe: Can be called from multiple threads simultaneously.
Statistics counters are updated atomically.

Definition at line 371 of file asciichat_errno.c.

371 {
372 if (!lifecycle_is_initialized(&g_error_stats.lifecycle)) {
373 if (lifecycle_init(&g_error_stats.lifecycle, "error_stats")) {
374 mutex_init(&g_error_stats.mutex, "error_stats");
375 memset(&g_error_stats.stats, 0, sizeof(g_error_stats.stats));
376 }
377 }
378
379 mutex_lock(&g_error_stats.mutex);
380
381 if (code >= 0 && code < 256) {
382 g_error_stats.stats.error_counts[code]++;
383 }
384 g_error_stats.stats.total_errors++;
385 g_error_stats.stats.last_error_time = time_ns_to_us(time_get_realtime_ns());
386 g_error_stats.stats.last_error_code = code;
387
388 mutex_unlock(&g_error_stats.mutex);
389}
uint64_t time_get_realtime_ns(void)
Get current wall-clock (real) time in nanoseconds.
Definition util/time.c:119
int mutex_init(mutex_t *mutex, const char *name)
Initialize a mutex with a name.
Definition threading.c:16

References lifecycle_init(), lifecycle_is_initialized(), mutex_init(), mutex_lock, mutex_unlock, and time_get_realtime_ns().

Referenced by asciichat_set_errno().

◆ asciichat_error_stats_reset()

void asciichat_error_stats_reset ( void  )

#include <asciichat_errno.h>

Reset all error statistics to zero.

Resets all error statistics counters to zero. Useful for resetting statistics between test runs or monitoring periods.

Note
Thread-safe: Can be called from any thread.
All counters are reset to zero (total_errors, error_counts, etc.).

Definition at line 432 of file asciichat_errno.c.

432 {
433 if (lifecycle_is_initialized(&g_error_stats.lifecycle)) {
434 mutex_lock(&g_error_stats.mutex);
435 memset(&g_error_stats.stats, 0, sizeof(g_error_stats.stats));
436 mutex_unlock(&g_error_stats.mutex);
437 }
438}

References lifecycle_is_initialized(), mutex_lock, and mutex_unlock.

◆ asciichat_fatal_with_context()

void asciichat_fatal_with_context ( asciichat_error_t  code,
const char *  file,
int  line,
const char *  function,
const char *  format,
  ... 
)

#include <asciichat_errno.h>

Exit with error code and context (used by FATAL macro)

Parameters
codeError code (asciichat_error_t)
fileSource file name (can be NULL)
lineLine number (0 if not provided)
functionFunction name (can be NULL)
formatFormat string (printf-style)
...Format arguments

Low-level function used by FATAL() macro. Sets error context and exits the program with the specified error code. In debug builds, prints stack trace before exiting.

Note
This function never returns (terminates program).
In debug builds, prints full error context and stack trace.
Thread-safe: Uses thread-local storage.
Warning
This function terminates the program. Use FATAL() macro instead of calling this directly.

Definition at line 261 of file asciichat_errno.c.

262 {
263 (void)file;
264 (void)line;
265 (void)function;
266
267 // Print library error context if available
269 if (HAS_ERRNO(&err_ctx)) {
270 log_labeled("\nasciichat_errno: libary code error context", LOG_COLOR_ERROR, "");
272 } else {
273 log_plain("WARNING: No error context found (asciichat_errno_context.code=%d)", asciichat_errno_context.code);
274 }
275
276 safe_fprintf(stderr, "\n");
277 log_labeled("FATAL ERROR", LOG_COLOR_FATAL, "exit code %d (%s)", (int)code, asciichat_error_string(code));
278#ifndef NDEBUG
279 const char *relative_file = extract_project_relative_path(file);
280 log_plain(" Location: %s:%d in %s()", relative_file, line, function);
281#endif
282
283 if (format) {
284 va_list args;
285 va_start(args, format);
286 char *formatted_message = format_message(format, args);
287 log_plain(" Error message: %s", formatted_message);
288 SAFE_FREE(formatted_message);
289 va_end(args);
290 }
291
292#ifndef NDEBUG
293 // Always print platform backtrace in debug/dev builds
294 backtrace_t bt = {0};
296 if (bt.count > 0) {
297 backtrace_print("\nFATAL BACKTRACE", &bt, 0, 0, skip_backtrace_frame);
298 backtrace_t_free(&bt);
299 }
300#endif
301
302#ifdef EMSCRIPTEN_BUILD
303 // In WASM builds, do not call exit() — it permanently kills the module runtime.
304 // Instead, set the error and return so callers can handle it gracefully.
305 SET_ERRNO(code, "FATAL (non-exit in WASM): code=%d", (int)code);
306#else
307 exit(code);
308#endif
309}
void backtrace_capture_and_symbolize(backtrace_t *bt)
Capture and symbolize in one call.
void backtrace_print(const char *label, const backtrace_t *bt, int skip_frames, int max_frames, backtrace_frame_filter_t filter)
Print backtrace with dual output: colored stderr + plain log file.
void asciichat_print_error_context(const asciichat_error_context_t *context)
Print full error context to stderr.
char * format_message(const char *format, va_list args)
Format a message using va_list.
Definition log/log.c:248
void log_labeled(const char *label, log_color_t color, const char *message,...)
Print a labeled message with color.
@ LOG_COLOR_FATAL
Definition log/log.h:136
@ LOG_COLOR_ERROR
Definition log/log.h:135
int safe_fprintf(FILE *stream, const char *format,...)
Safe formatted output to file stream.
Definition system.c:172
const char * extract_project_relative_path(const char *file)
Extract relative path from an absolute path.
Definition path.c:456
action_args_t args
int count
Number of frames captured.

◆ asciichat_get_errno()

asciichat_error_t asciichat_get_errno ( void  )

#include <asciichat_errno.h>

Get current error code.

Returns
Current error code (ASCIICHAT_OK if no error)

Returns the current thread-local error code. Returns ASCIICHAT_OK if no error has occurred. This is the low-level function used by GET_ERRNO().

Note
Thread-safe: Uses thread-local storage.
For full error context, use HAS_ERRNO() instead.
Warning
Use GET_ERRNO() macro instead of calling this directly.

Definition at line 252 of file asciichat_errno.c.

252 {
254}

References asciichat_errno_context, and asciichat_error_context_t::code.

◆ asciichat_get_thread_error()

asciichat_error_t asciichat_get_thread_error ( int  thread_id)

#include <asciichat_errno.h>

Get error code for a specific thread.

Parameters
thread_idThread ID to query
Returns
Error code for thread, or ASCIICHAT_OK if no error

Retrieves the error code for a specific thread. Useful for checking errors from other threads or propagating errors across thread boundaries.

Note
Thread ID must be valid (positive integer).
Returns ASCIICHAT_OK if thread has no error or thread ID is invalid.

Definition at line 457 of file asciichat_errno.c.

457 {
458 for (int i = 0; i < MAX_THREAD_ERRORS; i++) {
459 if (thread_errors[i].valid && thread_errors[i].thread_id == thread_id) {
460 return thread_errors[i].error_code;
461 }
462 }
463 return ASCIICHAT_OK;
464}

References ASCIICHAT_OK, MAX_THREAD_ERRORS, thread_id, and valid.

◆ asciichat_has_errno()

bool asciichat_has_errno ( asciichat_error_context_t *  context)

#include <asciichat_errno.h>

Check if error occurred and get full context.

Parameters
contextOutput structure for error context (must not be NULL)
Returns
true if error occurred, false if no error

Checks if an error has occurred and copies the full error context into the provided structure. This is the low-level function used by HAS_ERRNO().

Note
Returns false if no error has occurred (asciichat_errno == ASCIICHAT_OK).
If error occurred, context structure is filled with all error information.
Thread-safe: Uses thread-local storage.
Warning
Use HAS_ERRNO() macro instead of calling this directly.

Definition at line 221 of file asciichat_errno.c.

221 {
223 return false;
224 }
225
226 if (context) {
227 *context = asciichat_errno_context;
228 }
229
230 return true;
231}

References asciichat_errno_context, ASCIICHAT_OK, and asciichat_error_context_t::code.

◆ asciichat_has_wsa_error()

bool asciichat_has_wsa_error ( void  )

#include <asciichat_errno.h>

Check if current error has WSA error code.

Returns
true if error has WSA error code, false otherwise

Checks whether the current thread-local error context includes a Windows socket error (WSA error) code. Useful for platform-specific error handling.

Note
Only meaningful on Windows platforms.
Returns false if no error occurred or error doesn't have WSA code.
Thread-safe: Uses thread-local storage.

Definition at line 212 of file asciichat_errno.c.

212 {
214}

References asciichat_errno_context, and asciichat_error_context_t::has_wsa_error.

◆ asciichat_print_error_context()

void asciichat_print_error_context ( const asciichat_error_context_t *  context)

#include <asciichat_errno.h>

Print full error context to stderr.

Parameters
contextError context to print (must not be NULL)

Prints comprehensive error information including error code, location, context message, system errors, and stack trace (if available) to stderr. Useful for debugging and error reporting.

Note
Stack trace is only printed in debug builds.
System errors (errno, WSA) are included if present.
Timestamp and location information are included.

Definition at line 316 of file asciichat_errno.c.

316 {
317 if (!context || context->code == ASCIICHAT_OK) {
318 return;
319 }
320
321 if (context->file && context->line && context->function) {
322 log_plain(" Location: %s:%d in %s()", extract_project_relative_path(context->file), context->line,
323 context->function);
324 } else {
325 log_plain(" Location: unknown (set by system code)");
326 }
327
328 if (context->context_message) {
329 safe_fprintf(stderr, " %s %s\n", colored_string(LOG_COLOR_WARN, "Context:"), context->context_message);
330 log_file(" Context: %s", context->context_message);
331 }
332
333 if (context->has_system_error) {
334 log_plain(" System error: %s (code: %d, meaning: %s)", SAFE_STRERROR(context->system_errno), context->system_errno,
335 SAFE_STRERROR(context->system_errno));
336 }
337
338 // Print timestamp
339 if (context->timestamp > 0) {
340 time_t sec = (time_t)(context->timestamp / NS_PER_MS_INT);
341 long usec = (long)(context->timestamp % NS_PER_MS_INT);
342 struct tm tm_info;
343 if (platform_localtime(&sec, &tm_info) == ASCIICHAT_OK) {
344 char time_str[64];
345 (void)strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm_info);
346 log_plain(" Timestamp: %s.%06ld", time_str, usec);
347 }
348 }
349
350 // Print stack trace from library error
351 if (context->backtrace.count > 0) {
352 // Symbolize backtrace only when actually printing it (not at capture time)
354 if (context->backtrace.symbols) {
355 backtrace_print("\nBacktrace from library error", &context->backtrace, 0, 0, skip_backtrace_frame);
356 }
357 }
358}
void backtrace_symbolize(backtrace_t *bt)
Symbolize bt->ptrs into bt->symbols.
#define SAFE_STRERROR(errnum)
Definition common.h:465
#define log_file(...)
File-only logging - writes to log file only, no stderr output.
Definition log/log.h:646
@ LOG_COLOR_WARN
Definition log/log.h:134
const char * colored_string(log_color_t color, const char *text)
Build a colored string for terminal output.
uint64_t timestamp
Timestamp when error occurred (microseconds since epoch)
char ** symbols
Symbolized strings (NULL until backtrace_symbolize called)

References ASCIICHAT_OK, asciichat_error_context_t::backtrace, backtrace_print(), backtrace_symbolize(), asciichat_error_context_t::code, colored_string(), asciichat_error_context_t::context_message, backtrace_t::count, extract_project_relative_path(), asciichat_error_context_t::file, asciichat_error_context_t::function, asciichat_error_context_t::has_system_error, asciichat_error_context_t::line, LOG_COLOR_WARN, log_file, log_plain, NS_PER_MS_INT, platform_localtime(), safe_fprintf(), SAFE_STRERROR, backtrace_t::symbols, asciichat_error_context_t::system_errno, and asciichat_error_context_t::timestamp.

Referenced by asciichat_fatal_with_context().

◆ asciichat_set_errno()

void asciichat_set_errno ( asciichat_error_t  code,
const char *  file,
int  line,
const char *  function,
const char *  context_message 
)

#include <asciichat_errno.h>

Set error code with basic context.

Parameters
codeError code to set (asciichat_error_t)
fileSource file name (can be NULL)
lineLine number (0 if not provided)
functionFunction name (can be NULL)
context_messageCustom context message (can be NULL, will be copied)

Sets the thread-local error code with basic context information. This is the low-level function used by SET_ERRNO() macros.

Note
In debug builds, automatically captures stack trace if enabled.
Context message is copied if provided (caller can free original).
Thread-safe: Uses thread-local storage (no synchronization needed).
Warning
Use SET_ERRNO() macros instead of calling this directly.

Definition at line 113 of file asciichat_errno.c.

114 {
115 // Suppress error context allocation during cleanup to prevent leaks
116 if (g_suppress_error_context) {
117 return;
118 }
119
120 // Clear any existing context message
124 }
125
126 // Set the error context
133
134 // Set the simple error code variable
135 asciichat_errno = code;
136
137 // Copy context message if provided
138 if (context_message == NULL) {
139 log_error("context_message is NULL");
140 const char *fallback = "No context message (this is invalid - set a context message)";
141 size_t len = strlen(fallback) + 1;
145 } else {
146 log_error("SAFE_MALLOC failed for fallback context_message");
147 }
148 } else {
149 size_t len = strlen(context_message) + 1;
153 } else {
154 log_error("SAFE_MALLOC failed for context_message");
155 }
156 }
157
158 // Capture stack trace in debug builds
160 capture_backtrace(&asciichat_errno_context.backtrace);
161
162 // Record in statistics
164}
#define SAFE_STRNCPY(dst, src, size)
Definition common.h:414
__thread asciichat_error_t asciichat_errno
Thread-local current error code.
void asciichat_error_stats_record(asciichat_error_t code)
Record an error in statistics.

References asciichat_errno, asciichat_errno_context, asciichat_error_stats_record(), asciichat_error_context_t::backtrace, backtrace_t_free(), asciichat_error_context_t::code, asciichat_error_context_t::context_message, asciichat_error_context_t::file, asciichat_error_context_t::function, asciichat_error_context_t::has_system_error, asciichat_error_context_t::line, log_error, SAFE_FREE, SAFE_MALLOC, SAFE_STRNCPY, time_get_realtime_ns(), and asciichat_error_context_t::timestamp.

Referenced by asciichat_set_errno_with_message(), asciichat_set_errno_with_system_error(), asciichat_set_errno_with_system_error_and_message(), and asciichat_set_errno_with_wsa_error().

◆ asciichat_set_errno_with_message()

void asciichat_set_errno_with_message ( asciichat_error_t  code,
const char *  file,
int  line,
const char *  function,
const char *  format,
  ... 
)

#include <asciichat_errno.h>

Set error code with formatted message.

Parameters
codeError code to set (asciichat_error_t)
fileSource file name (can be NULL)
lineLine number (0 if not provided)
functionFunction name (can be NULL)
formatFormat string (printf-style)
...Format arguments

Sets the thread-local error code with a formatted context message. This is the low-level function used by SET_ERRNO() macros.

Note
Message is formatted using vsnprintf and stored in error context.
In debug builds, automatically captures stack trace if enabled.
Thread-safe: Uses thread-local storage.
Warning
Use SET_ERRNO() macros instead of calling this directly.

Definition at line 166 of file asciichat_errno.c.

167 {
168 va_list args;
169 va_start(args, format);
170
171 char *context_message = format_message(format, args);
172 asciichat_set_errno(code, file, line, function, context_message);
173
174 if (context_message) {
175 SAFE_FREE(context_message);
176 }
177
178 va_end(args);
179}
void asciichat_set_errno(asciichat_error_t code, const char *file, int line, const char *function, const char *context_message)
Set error code with basic context.

References args, asciichat_set_errno(), format_message(), and SAFE_FREE.

◆ asciichat_set_errno_with_system_error()

void asciichat_set_errno_with_system_error ( asciichat_error_t  code,
const char *  file,
int  line,
const char *  function,
int  sys_errno 
)

#include <asciichat_errno.h>

Set error code with system error (errno)

Parameters
codeError code to set (asciichat_error_t)
fileSource file name (can be NULL)
lineLine number (0 if not provided)
functionFunction name (can be NULL)
sys_errnoSystem errno value

Sets the thread-local error code with system error context. Captures the system errno value for detailed error reporting.

Note
System errno is stored in error context for later retrieval.
In debug builds, automatically captures stack trace if enabled.
Thread-safe: Uses thread-local storage.
Warning
Use SET_ERRNO_SYS() macro instead of calling this directly.

Definition at line 181 of file asciichat_errno.c.

182 {
183 asciichat_set_errno(code, file, line, function, NULL);
186}

References asciichat_errno_context, asciichat_set_errno(), asciichat_error_context_t::has_system_error, and asciichat_error_context_t::system_errno.

◆ asciichat_set_errno_with_system_error_and_message()

void asciichat_set_errno_with_system_error_and_message ( asciichat_error_t  code,
const char *  file,
int  line,
const char *  function,
int  sys_errno,
const char *  format,
  ... 
)

#include <asciichat_errno.h>

Set error code with system error and formatted message.

Parameters
codeError code to set (asciichat_error_t)
fileSource file name (can be NULL)
lineLine number (0 if not provided)
functionFunction name (can be NULL)
sys_errnoSystem errno value
formatFormat string (printf-style)
...Format arguments

Sets the thread-local error code with both system error context and a formatted message. This is the low-level function used by SET_ERRNO_SYS().

Note
Combines system error capture with formatted message.
In debug builds, automatically captures stack trace if enabled.
Thread-safe: Uses thread-local storage.
Warning
Use SET_ERRNO_SYS() macro instead of calling this directly.

Definition at line 188 of file asciichat_errno.c.

189 {
190 va_list args;
191 va_start(args, format);
192
193 char *context_message = format_message(format, args);
194 asciichat_set_errno(code, file, line, function, context_message);
197
198 if (context_message) {
199 SAFE_FREE(context_message);
200 }
201
202 va_end(args);
203}

References args, asciichat_errno_context, asciichat_set_errno(), format_message(), asciichat_error_context_t::has_system_error, SAFE_FREE, and asciichat_error_context_t::system_errno.

◆ asciichat_set_errno_with_wsa_error()

void asciichat_set_errno_with_wsa_error ( asciichat_error_t  code,
const char *  file,
int  line,
const char *  function,
int  wsa_error 
)

#include <asciichat_errno.h>

Set error code with Windows socket error (WSA error)

Parameters
codeError code to set (asciichat_error_t)
fileSource file name (can be NULL)
lineLine number (0 if not provided)
functionFunction name (can be NULL)
wsa_errorWindows socket error code

Sets the thread-local error code with Windows-specific socket error context. Used for Windows socket operations that fail with WSA error codes.

Note
WSA error is stored in error context for later retrieval.
This function is only useful on Windows platforms.
Thread-safe: Uses thread-local storage.

Definition at line 205 of file asciichat_errno.c.

206 {
207 asciichat_set_errno(code, file, line, function, NULL);
210}

References asciichat_errno_context, asciichat_set_errno(), asciichat_error_context_t::has_wsa_error, and asciichat_error_context_t::wsa_error.

◆ asciichat_set_thread_error()

void asciichat_set_thread_error ( int  thread_id,
asciichat_error_t  code 
)

#include <asciichat_errno.h>

Set error code for a specific thread.

Parameters
thread_idThread ID to set error for
codeError code to set (asciichat_error_t)

Sets the error code for a specific thread. Useful for propagating errors from one thread to another or storing thread-specific error states.

Note
Thread ID must be valid (positive integer).
This is separate from thread-local error state (asciichat_errno).

Definition at line 466 of file asciichat_errno.c.

466 {
467 // Find existing entry or empty slot
468 int slot = -1;
469 for (int i = 0; i < MAX_THREAD_ERRORS; i++) {
470 if (thread_errors[i].valid && thread_errors[i].thread_id == thread_id) {
471 slot = i;
472 break;
473 }
474 if (!thread_errors[i].valid && slot == -1) {
475 slot = i;
476 }
477 }
478
479 if (slot >= 0) {
480 thread_errors[slot].thread_id = thread_id;
481 thread_errors[slot].error_code = code;
482 thread_errors[slot].valid = true;
483 }
484}

References MAX_THREAD_ERRORS, thread_id, and valid.

Variable Documentation

◆ asciichat_errno

__thread asciichat_error_t asciichat_errno
extern

#include <asciichat_errno.h>

Thread-local current error code.

Current error code for the calling thread. Set to ASCIICHAT_OK when no error. Updated automatically when errors are set via SET_ERRNO() macros.

Note
Use GET_ERRNO() macro to read the current error code.
Use CLEAR_ERRNO() macro to clear the error state.

Definition at line 43 of file asciichat_errno.c.

Referenced by accept_with_timeout(), asciichat_set_errno(), and recv_with_timeout().

◆ asciichat_errno_context

__thread asciichat_error_context_t asciichat_errno_context
extern

#include <asciichat_errno.h>

Thread-local error context storage.

Each thread has its own independent error context. This ensures thread-safe error handling without synchronization overhead.

Note
Use HAS_ERRNO() macro to check for errors and get context.
Context is automatically updated when errors are set via SET_ERRNO().

Definition at line 33 of file asciichat_errno.c.

33 {.code = ASCIICHAT_OK,
34 .file = NULL,
35 .line = 0,
36 .function = NULL,
37 .context_message = NULL,
38 .timestamp = 0,
39 .system_errno = 0,
40 .backtrace = {.count = 0, .symbols = NULL},
41 .has_system_error = false};

Referenced by accept_with_timeout(), asciichat_clear_errno(), asciichat_errno_destroy(), asciichat_fatal_with_context(), asciichat_get_errno(), asciichat_has_errno(), asciichat_has_wsa_error(), asciichat_set_errno(), asciichat_set_errno_with_system_error(), asciichat_set_errno_with_system_error_and_message(), asciichat_set_errno_with_wsa_error(), and recv_with_timeout().