ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
asciichat_errno.h
Go to the documentation of this file.
1#pragma once
8
9/* Existing buffer budgets in bytes, including NUL for text storage. */
10#define ASCIICHAT_ERROR_COUNTER_CAPACITY 256
11
12/* Existing buffer budgets in bytes, including NUL for text storage. */
13#define ASCIICHAT_BACKTRACE_FRAME_CAPACITY 32
14
15#include <stdbool.h>
16#include <stddef.h>
17#include <stdint.h>
18#include <libplatform/debug/backtrace.h>
19#include "common/error_codes.h"
20#include "common.h"
21#include "log/log.h"
22
23#define ASCIICHAT_ERRNO_MESSAGE_MAX 1024
24#define ASCIICHAT_ERRNO_MAX_DEPTH 64
25#define ASCIICHAT_ERRNO_MAX_THREADS 256
26#define ASCIICHAT_ERRNO_MAX_FRAMES 1024
27#define ASCIICHAT_ERRNO_HISTORY_SIZE 128
28
38const char *asciichat_error_format(const char *message, asciichat_error_t code);
39
67
74
82
96
97typedef struct {
98 size_t total;
99 size_t copied;
101
116
117#ifdef __cplusplus
118extern "C" {
119#endif
120
121asciichat_error_t errno_set(asciichat_error_t code, const char *file, int line, const char *function,
122 const char *message);
123asciichat_error_t errno_set_with_message(asciichat_error_t code, const char *file, int line, const char *function,
124 const char *format, ...);
125asciichat_error_t errno_set_with_system_error(asciichat_error_t code, const char *file, int line, const char *function,
126 int sys_errno);
128 const char *function, int sys_errno, const char *format, ...);
129asciichat_error_t errno_set_with_wsa_error(asciichat_error_t code, const char *file, int line, const char *function,
130 int wsa_error);
131
132// Arguments evaluate once. Capture errno before evaluating message arguments.
133#define SET_ERRNO(code, ...) errno_set_with_message((code), __FILE__, __LINE__, __func__, __VA_ARGS__)
134#define SET_ERRNO_SYS(code, ...) \
135 ({ \
136 int _asciichat_saved_errno = platform_get_last_error(); \
137 errno_set_with_system_error_and_message((code), __FILE__, __LINE__, __func__, _asciichat_saved_errno, \
138 __VA_ARGS__); \
139 })
140
144bool errno_has_code_tid(uint64_t thread_id, asciichat_error_t code);
151bool errno_has_wsa_error(void);
153void errno_print_chain(uint64_t thread_id, uint64_t error_id);
156void errno_clear(void);
157void errno_clear_all(void);
158void errno_clear_thread_error(uint64_t thread_id);
159void errno_clear_thread_errors(uint64_t thread_id);
160bool errno_clear_if_top(uint64_t thread_id, uint64_t generation, uint64_t error_id);
162bool errno_clear_if_current(uint64_t thread_id, uint64_t generation, uint64_t error_id);
163// Observe a suboperation without severing its causal link to the caller.
167
171size_t errno_threads_snapshot(uint64_t *out, size_t capacity);
185size_t errno_notifications_snapshot(asciichat_error_context_t *out, size_t capacity, uint64_t *dropped);
188bool errno_notifications_suppress(bool suppress);
189void errno_print_stacks(void);
190void errno_print_history(void);
191void errno_print_hash_stats(void);
192// Per-thread automatic logging suppression; storage is never suppressed.
193void errno_suppress(bool suppress);
194// Idempotent current-thread cleanup. Does not disable other threads.
195void errno_destroy(void);
196// Process shutdown, after producers and readers have joined.
197void errno_shutdown(void);
200
206void asciichat_fatal_with_context(asciichat_error_t code, const char *file, int line, const char *function,
207 const char *format, ...);
209
210#define HAS_ERRNO(context) errno_has(context)
211#define HAS_ERRNO_CODE(code) errno_has_code(code)
212#define HAS_ERRNO_CODE_TID(tid, code) errno_has_code_tid((tid), (code))
213#define HAS_ERRNO_CODE_SINCE(scope, code) errno_has_code_since((scope), (code))
214#define GET_ERRNO() errno_get()
215#define CLEAR_ERRNO() errno_clear()
216#define CLEAR_ERRNO_ALL() errno_clear_all()
217#define CLEAR_ERRNO_TID(tid) errno_clear_thread_error(tid)
218#define CLEAR_ERRNO_ALL_TID(tid) errno_clear_thread_errors(tid)
219#define PRINT_ERRNO_CONTEXT(context) asciichat_print_error_context(context)
220#define LOG_ERRNO_IF_SET(message) \
221 do { \
222 asciichat_error_context_t _ctx; \
223 if (HAS_ERRNO(&_ctx)) { \
224 log_error("%s", (message)); \
225 errno_print_chain(_ctx.thread_id, _ctx.error_id); \
226 } \
227 } while (0)
228#define LOG_ERRNO_IF_CODE(error_code, message) \
229 do { \
230 asciichat_error_context_t _ctx; \
231 if (HAS_ERRNO(&_ctx) && _ctx.code == (error_code)) { \
232 log_error("%s", (message)); \
233 errno_print_chain(_ctx.thread_id, _ctx.error_id); \
234 } \
235 } while (0)
236#define PRINT_ERRNO_IF_ERROR() LOG_ERRNO_IF_SET("Pending error")
237#ifndef NDEBUG
238#define ASSERT_NO_ERRNO_SINCE(scope) \
239 do { \
240 if (!errno_scope_is_clean(scope)) \
241 FATAL(ERROR_INVALID_STATE, "Successful operation left unresolved errors"); \
242 } while (0)
243#define ASSERT_NO_ERRNO() \
244 do { \
245 asciichat_error_context_t _ctx; \
246 if (HAS_ERRNO(&_ctx)) { \
247 asciichat_print_error_context(&_ctx); \
248 FATAL(_ctx.code, "Unresolved error at operation boundary"); \
249 } \
250 } while (0)
251#else
252#define ASSERT_NO_ERRNO_SINCE(scope) ((void)(scope))
253#define ASSERT_NO_ERRNO() ((void)0)
254#endif
255
256#ifdef __cplusplus
257}
258#endif
asciichat_error_t errno_set_with_message(asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
void errno_clear_all(void)
bool errno_has_code_since(asciichat_errno_scope_t scope, asciichat_error_t code)
#define ASCIICHAT_ERRNO_MESSAGE_MAX
void errno_request_exit(asciichat_error_t code)
void errno_notifications_dismiss(uint64_t through_id)
bool errno_peek_since(asciichat_errno_scope_t scope, asciichat_error_context_t *out)
void errno_scope_end(asciichat_errno_scope_t scope, asciichat_errno_outcome_t outcome)
asciichat_error_t errno_exit_code(void)
bool errno_notifications_pending(void)
void errno_notifications_pause(void)
asciichat_error_t errno_set_with_system_error(asciichat_error_t code, const char *file, int line, const char *function, int sys_errno)
void asciichat_fatal_with_context(asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
void errno_shutdown(void)
size_t errno_notifications_snapshot(asciichat_error_context_t *out, size_t capacity, uint64_t *dropped)
bool errno_has(asciichat_error_context_t *context)
void errno_clear_thread_error(uint64_t thread_id)
void asciichat_error_stats_print(void)
void errno_clear_thread_errors(uint64_t thread_id)
size_t errno_threads_snapshot(uint64_t *out, size_t capacity)
void errno_print_history(void)
bool errno_has_wsa_error(void)
asciichat_error_t errno_get(void)
bool errno_notifications_suppress(bool suppress)
asciichat_error_t errno_set(asciichat_error_t code, const char *file, int line, const char *function, const char *message)
asciichat_errno_scope_t errno_checkpoint(void)
void errno_print_chain(uint64_t thread_id, uint64_t error_id)
asciichat_error_stats_t asciichat_error_stats_get(void)
void asciichat_error_stats_init(void)
asciichat_error_t errno_set_with_wsa_error(asciichat_error_t code, const char *file, int line, const char *function, int wsa_error)
asciichat_errno_scope_t errno_scope_begin(void)
size_t errno_history_snapshot(asciichat_errno_history_t *out, size_t capacity)
const char * asciichat_error_format(const char *message, asciichat_error_t code)
asciichat_errno_outcome_t
@ ASCIICHAT_ERRNO_THREAD_EXIT
@ ASCIICHAT_ERRNO_HANDLED
@ ASCIICHAT_ERRNO_DISMISSED
@ ASCIICHAT_ERRNO_OVERFLOW
void errno_destroy(void)
bool errno_clear_if_top(uint64_t thread_id, uint64_t generation, uint64_t error_id)
void asciichat_error_stats_reset(void)
asciichat_error_t errno_import(const asciichat_error_context_t *cause)
asciichat_error_t errno_set_with_system_error_and_message(asciichat_error_t code, const char *file, int line, const char *function, int sys_errno, const char *format,...)
#define ASCIICHAT_ERROR_COUNTER_CAPACITY
asciichat_error_t errno_get_thread_error(uint64_t thread_id)
void errno_print_hash_stats(void)
void errno_print_stacks(void)
bool errno_scope_is_clean(asciichat_errno_scope_t scope)
bool errno_clear_if_current(uint64_t thread_id, uint64_t generation, uint64_t error_id)
bool errno_has_code_tid(uint64_t thread_id, asciichat_error_t code)
void errno_notifications_enable(bool enabled)
asciichat_errno_snapshot_t errno_snapshot(uint64_t thread_id, asciichat_error_context_t *out, size_t capacity)
bool errno_has_thread_error(uint64_t thread_id, asciichat_error_context_t *context)
void errno_suppress(bool suppress)
void asciichat_print_error_context(const asciichat_error_context_t *context)
bool errno_has_code(asciichat_error_t code)
void asciichat_error_stats_record(asciichat_error_t code)
size_t errno_title_snapshot(asciichat_error_context_t *latest)
void errno_clear(void)
⚙️ Common definitions, error codes, macros, and types shared throughout the application
Error and exit codes - unified status values (0-255).
bool enabled
Is filtering active?
Definition grep.c:62
unsigned long long uint64_t
Definition common.h:63
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
📝 Logging API with multiple log levels and terminal output control
static bool size_t gotel_query_t * out
Definition queries.h:8
asciichat_error_context_t context
asciichat_errno_outcome_t outcome
When code needs to work with asciichat errno snapshot, it keeps total, copied here instead of scatter...
uint64_t created_ns
Monotonic time, for age.
uint64_t timestamp
Microseconds since epoch, for logs.
asciichat_error_t last_error_code