ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
errno.c
Go to the documentation of this file.
4#include <libplatform/thread.h>
5#include <libplatform/cond.h>
6#include <libplatform/atomic.h>
9
10static atomic_t g_debug_errno_signal = {0};
11static atomic_t g_debug_errno_exiting = {0};
12static atomic_t g_debug_errno_cleaning = {0};
13static platform_thread_t g_debug_errno_thread;
14static mutex_t g_debug_errno_mutex;
15static cond_t g_debug_errno_condition;
16static bool g_debug_errno_initialized;
17static bool g_debug_errno_started;
18static uint64_t g_debug_errno_errno_deadline;
19
21 if (g_debug_errno_initialized)
22 return ASCIICHAT_OK;
23 if (mutex_init(&g_debug_errno_mutex, "debug_errno") != 0)
24 return SET_ERRNO(ERROR_THREAD, "Cannot initialize diagnostics mutex");
25 if (cond_init(&g_debug_errno_condition, "debug_errno") != 0) {
26 mutex_destroy(&g_debug_errno_mutex);
27 return SET_ERRNO(ERROR_THREAD, "Cannot initialize diagnostics condition");
28 }
29 g_debug_errno_initialized = true;
30 atomic_store_bool_impl(&g_debug_errno_cleaning, false);
31 return ASCIICHAT_OK;
32}
33static void debug_errno_print_errno(void) {
34 log_info("Errno stacks:");
38}
40 debug_errno_print_errno();
41}
43 if (!g_debug_errno_initialized)
44 return;
45 debug_report_schedule(&g_debug_errno_mutex, &g_debug_errno_condition, &g_debug_errno_errno_deadline, delay);
46}
48 // Do not signal a condition variable or invoke diagnostic hooks in a signal
49 // handler. The worker checks this flag at most 100ms after its next wakeup.
50 atomic_store_bool_impl(&g_debug_errno_signal, true);
51}
53 return atomic_load_bool_impl(&g_debug_errno_cleaning);
54}
55void debug_errno_poll(void) {
56 if (!g_debug_errno_initialized)
57 return;
58 uint64_t now = time_get_ns();
59 bool all = atomic_exchange_bool_impl(&g_debug_errno_signal, false);
60 mutex_lock(&g_debug_errno_mutex);
61 bool errors = g_debug_errno_errno_deadline && now >= g_debug_errno_errno_deadline;
62 if (errors)
63 g_debug_errno_errno_deadline = 0;
64 mutex_unlock(&g_debug_errno_mutex);
65 if (all || errors)
66 debug_errno_print_errno();
67}
68#ifndef EMSCRIPTEN_BUILD
69static void *debug_errno_worker(void *unused) {
70 (void)unused;
71 while (!atomic_load_bool_impl(&g_debug_errno_exiting)) {
73 mutex_lock(&g_debug_errno_mutex);
74 uint64_t now = time_get_ns();
75 uint64_t wait = 100 * NS_PER_MS_INT;
76 uint64_t deadlines[] = {g_debug_errno_errno_deadline};
77 for (size_t i = 0; i < sizeof(deadlines) / sizeof(deadlines[0]); ++i)
78 if (deadlines[i]) {
79 uint64_t remaining = deadlines[i] > now ? deadlines[i] - now : 1;
80 if (remaining < wait)
81 wait = remaining;
82 }
83 if (!atomic_load_bool_impl(&g_debug_errno_exiting))
84 cond_timedwait(&g_debug_errno_condition, &g_debug_errno_mutex, wait);
85 mutex_unlock(&g_debug_errno_mutex);
86 }
87 return NULL;
88}
89#endif
91 if (g_debug_errno_started)
92 return ASCIICHAT_OK;
94 if (result != ASCIICHAT_OK)
95 return result;
96 atomic_store_bool_impl(&g_debug_errno_exiting, false);
97 atomic_store_bool_impl(&g_debug_errno_cleaning, false);
98 options_t *opts = options_get();
99 if (opts) {
100 if (IS_OPTION_EXPLICIT(debug_errno_stacks_time, opts))
102 }
103#ifndef EMSCRIPTEN_BUILD
104 if (platform_thread_create(&g_debug_errno_thread, "debug_errno", debug_errno_worker, NULL) != 0)
105 return SET_ERRNO(ERROR_THREAD, "Cannot start diagnostics worker");
106#endif
107 g_debug_errno_started = true;
108 return ASCIICHAT_OK;
109}
111 if (!g_debug_errno_started)
112 return;
113 atomic_store_bool_impl(&g_debug_errno_cleaning, true);
114 mutex_lock(&g_debug_errno_mutex);
115 atomic_store_bool_impl(&g_debug_errno_exiting, true);
116 cond_signal(&g_debug_errno_condition);
117 mutex_unlock(&g_debug_errno_mutex);
118#ifndef EMSCRIPTEN_BUILD
119 // Join fully: diagnostic data must not be destroyed while a reader is alive.
120 if (thread_join(&g_debug_errno_thread, NULL) != 0)
121 FATAL(ERROR_THREAD, "Cannot join diagnostics worker");
122#endif
123 g_debug_errno_started = false;
124}
127 if (g_debug_errno_initialized) {
128 cond_destroy(&g_debug_errno_condition);
129 mutex_destroy(&g_debug_errno_mutex);
130 g_debug_errno_initialized = false;
131 atomic_store_bool_impl(&g_debug_errno_signal, false);
132 g_debug_errno_errno_deadline = 0;
133 }
134}
void errno_print_history(void)
void errno_print_hash_stats(void)
void errno_print_stacks(void)
Synchronized per-thread pending error stacks and value snapshots. SET_ERRNO pushes,...
#define SET_ERRNO(code,...)
Dedicated worker for all pending errno stacks and handled history. Signal handlers may only request a...
void debug_report_schedule(mutex_t *mutex, cond_t *condition, uint64_t *deadline, uint64_t delay_ns)
Shared deadline and scheduling helpers for diagnostic reports.
bool debug_errno_is_cleanup_in_progress(void)
Definition errno.c:52
asciichat_error_t debug_errno_init(void)
Definition errno.c:20
void debug_errno_print(void)
Definition errno.c:39
void debug_errno_trigger_print(void)
Definition errno.c:47
void debug_errno_poll(void)
Definition errno.c:55
void debug_errno_print_delayed(uint64_t delay)
Definition errno.c:42
void debug_errno_destroy(void)
Definition errno.c:125
asciichat_error_t debug_errno_start_thread(void)
Definition errno.c:90
void debug_errno_cleanup_thread(void)
Definition errno.c:110
#define IS_OPTION_EXPLICIT(name, opts)
Definition explicit.h:57
#define FATAL(code,...)
Exit with error code and custom message, with stack trace in debug builds.
Definition common.h:160
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
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_THREAD
#define log_info(...)
Log an INFO message.
Definition log/log.h:608
#define NS_PER_SEC_INT
Definition time.h:169
#define NS_PER_MS_INT
Definition time.h:168
struct options_state options_t
Immutable, RCU-published snapshot of the application's runtime configuration.
const options_t * options_get(void)
Get pointer to current options struct (lock-free, thread-safe).
Definition rcu.c:511
⚙️ Unified options parsing system for ascii-chat with builder pattern and lock-free access
double debug_errno_stacks_time
Delay before the error report.
Definition options.h:1246
⏱️ High-precision timing utilities using sokol_time.h and uthash