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 File Reference

Synchronized per-thread pending error stacks and value snapshots. SET_ERRNO pushes, CLEAR_ERRNO pops. Recovery scopes resolve one attempt's errors. See docs/topics/errno.dox for ownership and capacity contracts. More...

Go to the source code of this file.

Data Structures

struct  asciichat_error_context_t
struct  asciichat_errno_history_t
struct  asciichat_errno_scope_t
 When code needs to work with asciichat errno snapshot, it keeps total, copied here instead of scattering it across globals. Initialization establishes the handles and sizes; teardown must release any allocation, lock, thread, or callback context recorded in those fields. More...
struct  asciichat_errno_snapshot_t
struct  asciichat_error_stats_t

Macros

#define ASCIICHAT_ERROR_COUNTER_CAPACITY   256
#define ASCIICHAT_BACKTRACE_FRAME_CAPACITY   32
#define ASCIICHAT_ERRNO_MESSAGE_MAX   1024
#define ASCIICHAT_ERRNO_MAX_DEPTH   64
#define ASCIICHAT_ERRNO_MAX_THREADS   256
#define ASCIICHAT_ERRNO_MAX_FRAMES   1024
#define ASCIICHAT_ERRNO_HISTORY_SIZE   128
#define SET_ERRNO(code, ...)
#define SET_ERRNO_SYS(code, ...)
#define HAS_ERRNO(context)
#define HAS_ERRNO_CODE(code)
#define HAS_ERRNO_CODE_TID(tid, code)
#define HAS_ERRNO_CODE_SINCE(scope, code)
#define GET_ERRNO()
#define CLEAR_ERRNO()
#define CLEAR_ERRNO_ALL()
#define CLEAR_ERRNO_TID(tid)
#define CLEAR_ERRNO_ALL_TID(tid)
#define PRINT_ERRNO_CONTEXT(context)
#define LOG_ERRNO_IF_SET(message)
#define LOG_ERRNO_IF_CODE(error_code, message)
#define PRINT_ERRNO_IF_ERROR()
#define ASSERT_NO_ERRNO_SINCE(scope)
#define ASSERT_NO_ERRNO()

Enumerations

enum  asciichat_errno_outcome_t { ASCIICHAT_ERRNO_HANDLED , ASCIICHAT_ERRNO_DISMISSED , ASCIICHAT_ERRNO_THREAD_EXIT , ASCIICHAT_ERRNO_OVERFLOW }

Functions

const char * asciichat_error_format (const char *message, asciichat_error_t code)
asciichat_error_t errno_set (asciichat_error_t code, const char *file, int line, const char *function, const char *message)
asciichat_error_t errno_set_with_message (asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
asciichat_error_t errno_set_with_system_error (asciichat_error_t code, const char *file, int line, const char *function, int sys_errno)
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,...)
asciichat_error_t errno_set_with_wsa_error (asciichat_error_t code, const char *file, int line, const char *function, int wsa_error)
bool errno_has (asciichat_error_context_t *context)
bool errno_has_thread_error (uint64_t thread_id, asciichat_error_context_t *context)
bool errno_has_code (asciichat_error_t code)
bool errno_has_code_tid (uint64_t thread_id, asciichat_error_t code)
bool errno_peek_since (asciichat_errno_scope_t scope, asciichat_error_context_t *out)
asciichat_error_t errno_import (const asciichat_error_context_t *cause)
bool errno_has_code_since (asciichat_errno_scope_t scope, asciichat_error_t code)
bool errno_has_wsa_error (void)
bool errno_scope_is_clean (asciichat_errno_scope_t scope)
void errno_print_chain (uint64_t thread_id, uint64_t error_id)
asciichat_error_t errno_get (void)
asciichat_error_t errno_get_thread_error (uint64_t thread_id)
void errno_clear (void)
void errno_clear_all (void)
void errno_clear_thread_error (uint64_t thread_id)
void errno_clear_thread_errors (uint64_t thread_id)
bool errno_clear_if_top (uint64_t thread_id, uint64_t generation, uint64_t error_id)
bool errno_clear_if_current (uint64_t thread_id, uint64_t generation, uint64_t error_id)
asciichat_errno_scope_t errno_checkpoint (void)
asciichat_errno_scope_t errno_scope_begin (void)
void errno_scope_end (asciichat_errno_scope_t scope, asciichat_errno_outcome_t outcome)
asciichat_errno_snapshot_t errno_snapshot (uint64_t thread_id, asciichat_error_context_t *out, size_t capacity)
size_t errno_threads_snapshot (uint64_t *out, size_t capacity)
size_t errno_history_snapshot (asciichat_errno_history_t *out, size_t capacity)
size_t errno_title_snapshot (asciichat_error_context_t *latest)
void errno_notifications_enable (bool enabled)
void errno_notifications_pause (void)
bool errno_notifications_pending (void)
size_t errno_notifications_snapshot (asciichat_error_context_t *out, size_t capacity, uint64_t *dropped)
void errno_notifications_dismiss (uint64_t through_id)
bool errno_notifications_suppress (bool suppress)
void errno_print_stacks (void)
void errno_print_history (void)
void errno_print_hash_stats (void)
void errno_suppress (bool suppress)
void errno_destroy (void)
void errno_shutdown (void)
void errno_request_exit (asciichat_error_t code)
asciichat_error_t errno_exit_code (void)
void asciichat_error_stats_init (void)
void asciichat_error_stats_record (asciichat_error_t code)
void asciichat_error_stats_print (void)
void asciichat_error_stats_reset (void)
asciichat_error_stats_t asciichat_error_stats_get (void)
void asciichat_fatal_with_context (asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)
void asciichat_print_error_context (const asciichat_error_context_t *context)

Detailed Description

Synchronized per-thread pending error stacks and value snapshots. SET_ERRNO pushes, CLEAR_ERRNO pops. Recovery scopes resolve one attempt's errors. See docs/topics/errno.dox for ownership and capacity contracts.

Definition in file asciichat_errno.h.

Macro Definition Documentation

◆ ASCIICHAT_BACKTRACE_FRAME_CAPACITY

#define ASCIICHAT_BACKTRACE_FRAME_CAPACITY   32

Definition at line 13 of file asciichat_errno.h.

◆ ASCIICHAT_ERRNO_HISTORY_SIZE

◆ ASCIICHAT_ERRNO_MAX_DEPTH

#define ASCIICHAT_ERRNO_MAX_DEPTH   64

◆ ASCIICHAT_ERRNO_MAX_FRAMES

#define ASCIICHAT_ERRNO_MAX_FRAMES   1024

Definition at line 26 of file asciichat_errno.h.

◆ ASCIICHAT_ERRNO_MAX_THREADS

#define ASCIICHAT_ERRNO_MAX_THREADS   256

◆ ASCIICHAT_ERRNO_MESSAGE_MAX

#define ASCIICHAT_ERRNO_MESSAGE_MAX   1024

◆ ASCIICHAT_ERROR_COUNTER_CAPACITY

#define ASCIICHAT_ERROR_COUNTER_CAPACITY   256

Definition at line 10 of file asciichat_errno.h.

◆ ASSERT_NO_ERRNO

#define ASSERT_NO_ERRNO ( )
Value:
do { \
if (HAS_ERRNO(&_ctx)) { \
asciichat_print_error_context(&_ctx); \
FATAL(_ctx.code, "Unresolved error at operation boundary"); \
} \
} while (0)
#define HAS_ERRNO(context)

Definition at line 243 of file asciichat_errno.h.

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)

◆ ASSERT_NO_ERRNO_SINCE

#define ASSERT_NO_ERRNO_SINCE ( scope)
Value:
do { \
if (!errno_scope_is_clean(scope)) \
FATAL(ERROR_INVALID_STATE, "Successful operation left unresolved errors"); \
} while (0)
bool errno_scope_is_clean(asciichat_errno_scope_t scope)
@ ERROR_INVALID_STATE

Definition at line 238 of file asciichat_errno.h.

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)

Referenced by audio_start_duplex(), config_load_and_apply(), config_load_system_and_user(), main(), media_source_create_interruptible(), and process_decrypted_packet().

◆ CLEAR_ERRNO

#define CLEAR_ERRNO ( )
Value:
void errno_clear(void)

Definition at line 215 of file asciichat_errno.h.

Referenced by session_capture_create(), session_handle_keyboard_input(), and ui_input_read_key().

◆ CLEAR_ERRNO_ALL

#define CLEAR_ERRNO_ALL ( )
Value:
void errno_clear_all(void)

Definition at line 216 of file asciichat_errno.h.

◆ CLEAR_ERRNO_ALL_TID

#define CLEAR_ERRNO_ALL_TID ( tid)
Value:
void errno_clear_thread_errors(uint64_t id)

Definition at line 218 of file asciichat_errno.h.

◆ CLEAR_ERRNO_TID

#define CLEAR_ERRNO_TID ( tid)
Value:
void errno_clear_thread_error(uint64_t id)

Definition at line 217 of file asciichat_errno.h.

◆ GET_ERRNO

#define GET_ERRNO ( )
Value:
asciichat_error_t errno_get(void)

Definition at line 214 of file asciichat_errno.h.

Referenced by acip_outbound_create(), and threaded_send_image_frame_encoded().

◆ HAS_ERRNO

◆ HAS_ERRNO_CODE

#define HAS_ERRNO_CODE ( code)
Value:
bool errno_has_code(asciichat_error_t code)

Definition at line 211 of file asciichat_errno.h.

◆ HAS_ERRNO_CODE_SINCE

#define HAS_ERRNO_CODE_SINCE ( scope,
code )
Value:
errno_has_code_since((scope), (code))
bool errno_has_code_since(asciichat_errno_scope_t scope, asciichat_error_t code)

Definition at line 213 of file asciichat_errno.h.

◆ HAS_ERRNO_CODE_TID

#define HAS_ERRNO_CODE_TID ( tid,
code )
Value:
errno_has_code_tid((tid), (code))
bool errno_has_code_tid(uint64_t id, asciichat_error_t code)

Definition at line 212 of file asciichat_errno.h.

◆ LOG_ERRNO_IF_CODE

#define LOG_ERRNO_IF_CODE ( error_code,
message )
Value:
do { \
if (HAS_ERRNO(&_ctx) && _ctx.code == (error_code)) { \
log_error("%s", (message)); \
errno_print_chain(_ctx.thread_id, _ctx.error_id); \
} \
} while (0)

Definition at line 228 of file asciichat_errno.h.

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)

◆ LOG_ERRNO_IF_SET

#define LOG_ERRNO_IF_SET ( message)
Value:
do { \
if (HAS_ERRNO(&_ctx)) { \
log_error("%s", (message)); \
errno_print_chain(_ctx.thread_id, _ctx.error_id); \
} \
} while (0)

Definition at line 220 of file asciichat_errno.h.

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)

Referenced by api_server_main(), audio_start_thread(), capture_start_thread(), client_protocol_start(), discovery_main(), keepalive_start_thread(), main(), mcp_http_run(), media_source_create_interruptible(), nat_upnp_open_protocol(), process_decrypted_packet(), server_main(), session_pipeline_destroy(), session_server_like_mdns_advertise(), session_server_like_run(), and stats_runtime_start().

◆ PRINT_ERRNO_CONTEXT

#define PRINT_ERRNO_CONTEXT ( context)
Value:
void asciichat_print_error_context(const asciichat_error_context_t *context)

Definition at line 219 of file asciichat_errno.h.

◆ PRINT_ERRNO_IF_ERROR

#define PRINT_ERRNO_IF_ERROR ( )
Value:
LOG_ERRNO_IF_SET("Pending error")
#define LOG_ERRNO_IF_SET(message)

Definition at line 236 of file asciichat_errno.h.

◆ SET_ERRNO

#define SET_ERRNO ( code,
... )
Value:
errno_set_with_message((code), __FILE__, __LINE__, __func__, __VA_ARGS__)
asciichat_error_t errno_set_with_message(asciichat_error_t code, const char *file, int line, const char *function, const char *format,...)

Definition at line 133 of file asciichat_errno.h.

Referenced by accept_with_timeout(), acds_client_connect(), acds_create_key_set_collect(), acds_handshake_receive(), acds_identity_default_path(), acds_identity_generate(), acds_identity_load(), acds_identity_save(), acds_protocol_create(), acds_protocol_enter(), acds_protocol_join(), acds_protocol_leave(), acds_protocol_lookup(), acds_protocol_receive(), acds_receive_packet(), acds_server_init(), acds_session_create(), acds_session_join(), acds_session_lookup(), acds_sign_session_create(), acds_sign_session_join(), acds_string_generate(), acds_transport_metadata_decode(), acds_transport_metadata_encode(), acds_verify_session_create(), acds_verify_session_join(), acip_client_receive_and_dispatch(), acip_client_receive_packet(), acip_handle_acds_packet(), acip_handle_client_packet(), acip_handle_server_packet(), acip_outbound_create(), acip_outbound_snapshot(), acip_outbound_submitv_ex(), acip_packet_encrypt(), acip_packet_open_sequence(), acip_packet_plan(), acip_packet_seal(), acip_render_settings_capabilities(), acip_render_settings_prepare(), acip_security_activate(), acip_security_decrypt(), acip_security_init_options(), acip_security_next_control(), acip_security_open(), acip_security_receive(), acip_security_rekey_encode(), acip_security_request_rekey(), acip_security_start(), acip_send_ascii_frame_contract(), acip_send_audio_batch(), acip_send_audio_opus(), acip_send_audio_opus_batch(), acip_send_capabilities(), acip_send_clear_console(), acip_send_error(), acip_send_image_frame(), acip_send_image_frame_h265(), acip_send_ping(), acip_send_pong(), acip_send_protocol_version(), acip_send_remote_log(), acip_send_server_state(), acip_send_session_created(), acip_send_session_info(), acip_send_session_joined(), acip_send_stream_start(), acip_send_stream_stop(), acip_server_receive_and_dispatch(), acip_server_send_error(), acip_server_validate_session_create(), acip_server_validate_session_join(), acip_settings_decode(), acip_settings_encode(), acip_settings_request(), acip_settings_send(), acip_tcp_transport_create(), acip_tcp_transport_set_zerocopy(), acip_transport_get_capabilities(), acip_transport_sendv_ex(), acip_webrtc_transport_create_secure(), acip_websocket_client_transport_create(), acip_websocket_runtime_create(), acip_websocket_server_transport_create(), acip_websocket_transport_flush(), add_known_host(), add_transport_client(), animation_apply(), animation_init(), animation_sample_at(), animation_set_speed(), animation_update(), apply_palette_config(), ascii_convert_with_buffers_stabilized(), ascii_create_grid(), ascii_frame_init(), ascii_grid_layout(), ascii_half_frame_init(), ascii_otel_init(), ascii_pad_frame_width(), ascii_render(), ascii_render_glyph_match_mode(), ascii_render_halfblocks(), ascii_stabilizer_prepare(), ascii_write(), asciichat_fatal_with_context(), asciichat_mdns_advertise(), asciichat_mdns_init(), asciichat_mdns_query(), asciichat_mdns_unadvertise(), asciichat_mdns_update(), asciichat_shared_init(), audio_connection_init(), audio_convert_channels(), audio_dequantize_samples(), audio_init(), audio_opus_configure_encoder(), audio_parse_batch_header(), audio_process_received_samples(), audio_processor_create(), audio_processor_process(), audio_read_samples(), audio_recording_create_channels(), audio_resample_stereo(), audio_ring_buffer_available_write(), audio_ring_buffer_create_format(), audio_ring_buffer_read(), audio_ring_buffer_write(), audio_route_capture(), audio_sender_init(), audio_start_duplex(), audio_stop_duplex(), audio_validate_batch_params(), audio_visualization_fft_init(), audio_write_samples(), av_send_audio_opus_batch(), broadcast_clear_console_to_all_clients(), browser_capture_transform_rgba(), browser_security_output(), browser_security_packet(), buffer_acquire(), buffer_budget_reserve(), buffer_domain_create(), buffer_set_size(), buffer_share(), buffer_unref(), buffer_workspace_reserve(), build_client_luminance_palette(), build_github_gpg_url(), build_github_ssh_url(), build_gitlab_gpg_url(), build_gitlab_ssh_url(), canonicalize_ipv6(), capture_init(), capture_start_thread(), check_and_record_packet_rate_limit(), check_and_record_rate_limit(), check_gpg_key_expiry(), check_key_expiry(), check_key_fingerprint(), check_key_patterns(), check_key_strength(), check_known_host_no_identity(), check_known_host_with_key(), cleanup_client_media_buffers(), client_configure_crypto_options(), client_connection_checkpoint(), client_connection_create(), client_connection_start(), client_crypto_init(), client_decode_frame_data(), client_decrypt_packet(), client_encrypt_packet(), client_generate_keypair(), client_get_crypto_error_message(), client_handle_auth_challenge(), client_handle_crypto_parameters(), client_handle_handshake_complete(), client_handle_key_exchange_init(), client_handshake_receive(), client_opus_decode(), client_opus_decoder_init(), client_opus_encode(), client_opus_encoder_init(), client_parse_gpg_private_key(), client_parse_gpg_private_key_binary(), client_parse_gpg_public_key(), client_parse_gpg_public_key_binary(), client_parse_ssh_private_key(), client_parse_ssh_public_key(), client_protocol_start(), client_public_key_bytes(), client_set_server_address(), client_validate_frame(), ClientSessionBinding::ClientSessionBinding(), colored_string_set_output_fd(), colorscheme_compile_scheme(), colorscheme_export_scheme(), colorscheme_init(), colorscheme_load_builtin(), colorscheme_load_from_file(), colorscheme_set_active_scheme(), compare_public_keys(), completions_generate_bash(), completions_generate_fish(), completions_generate_for_shell(), completions_generate_powershell(), completions_generate_zsh(), compress_data(), compress_workspace(), config_create_default(), config_load_and_apply(), config_schema_build_from_configs(), config_schema_get_all(), config_schema_get_by_category(), config_schema_get_by_toml_key(), connection_endpoint_resolve(), consensus_coordinator_create(), consensus_coordinator_get_current_host(), consensus_coordinator_on_collection_start(), consensus_coordinator_on_election_result(), consensus_coordinator_on_ring_members(), consensus_coordinator_on_stats_update(), consensus_coordinator_process(), consensus_create_for_discovery(), consensus_election_choose_hosts(), consensus_election_verify(), consensus_get_discovery_callbacks(), consensus_handoff_decode(), consensus_handoff_join(), consensus_handoff_receive(), consensus_metrics_collection_add(), consensus_metrics_collection_create(), consensus_metrics_collection_get(), consensus_metrics_from_wire(), consensus_metrics_measure(), consensus_metrics_to_wire(), consensus_state_add_metrics(), consensus_state_collection_complete(), consensus_state_compute_election(), consensus_state_create(), consensus_state_get_elected_backup(), consensus_state_get_elected_host(), consensus_state_get_metric_at(), consensus_state_reset_to_idle(), consensus_state_start_collection(), consensus_state_store_election(), consensus_topology_create(), consensus_topology_get_all(), consensus_topology_get_leader(), consensus_topology_get_next(), consensus_topology_get_prev(), MirrorFrameBinding::convert(), TerminalRendererBinding::copyPixels(), create_mixed_ascii_frame_for_client(), crypto_combine_auth_data(), crypto_compute_auth_response(), crypto_compute_hmac(), crypto_compute_hmac_ex(), crypto_compute_password_hmac(), crypto_create_auth_challenge(), crypto_create_encrypted_packet(), crypto_create_public_key_packet(), crypto_decrypt(), crypto_derive_password_encryption_key(), crypto_derive_password_key(), crypto_encrypt(), crypto_extract_auth_data(), crypto_generate_keypair(), crypto_generate_nonce(), crypto_get_public_key(), crypto_handshake_client_auth_response(), crypto_handshake_client_complete(), crypto_handshake_client_key_exchange(), crypto_handshake_init(), crypto_handshake_init_with_password(), crypto_handshake_server_auth_challenge(), crypto_handshake_server_complete(), crypto_handshake_server_send_parameters(), crypto_handshake_server_start(), crypto_handshake_set_parameters(), crypto_handshake_validate_packet_size(), crypto_init(), crypto_init_with_password(), crypto_policy_check_mode(), crypto_policy_resolve(), crypto_process_auth_challenge(), crypto_process_auth_response(), crypto_process_encrypted_packet(), crypto_process_public_key_packet(), crypto_random_bytes(), crypto_record_commit_epoch(), crypto_record_init(), crypto_record_open_sequence(), crypto_record_prepare_epoch(), crypto_record_retire_epoch_flow(), crypto_record_seal_into_domain(), crypto_regex_extract_gpg_keygrip(), crypto_regex_extract_pem_base64(), crypto_regex_match_known_hosts(), crypto_regex_match_public_key(), crypto_rekey_commit(), crypto_rekey_init(), crypto_rekey_process_request(), crypto_rekey_process_response(), crypto_rekey_session_init(), crypto_rekey_session_receive(), crypto_rekey_session_tick(), crypto_session_create(), crypto_session_lock(), crypto_set_peer_public_key(), crypto_sign_ephemeral_key(), crypto_validate_password(), crypto_verify_auth_response(), crypto_verify_hmac(), crypto_verify_hmac_ex(), crypto_verify_peer_signature(), database_init(), database_session_add_key(), database_session_clear_host(), database_session_create(), database_session_create_keys_with_transport(), database_session_get_keys(), database_session_join(), database_session_leave(), database_session_lookup(), database_session_revoke_key(), database_session_start_migration(), database_session_transport_get(), database_session_transport_set(), database_session_update_host(), database_session_update_host_with_transport(), database_stats_session_count(), database_stats_snapshot(), database_stats_unique_clients(), debug_errno_init(), debug_errno_start_thread(), debug_stats_init(), debug_stats_start_thread(), OpusCodecBinding::decode(), decompress_data(), decompress_data_exact(), detect_default_ssh_key(), discover_session_parallel(), discovery_keys_clear_cache(), discovery_keys_download_https(), discovery_keys_get_cache_path(), discovery_keys_load_cached(), discovery_keys_load_file(), discovery_keys_save_cached(), discovery_keys_verify(), discovery_keys_verify_change(), discovery_mdns_query(), discovery_session_check_host_alive(), discovery_session_create(), discovery_session_destroy(), discovery_session_get_host(), discovery_session_get_participant(), discovery_session_get_state(), discovery_session_get_string(), discovery_session_handle_host_disconnect(), discovery_session_is_active(), discovery_session_is_host(), discovery_session_process(), discovery_session_start(), discovery_session_stop(), display_init(), display_render_frame(), ducking_init(), ed25519_sign_message(), ed25519_to_x25519_private(), ed25519_to_x25519_public(), ed25519_verify_signature(), OpusCodecBinding::encode(), errno_import(), expand_ipv6(), extract_ed25519_from_gpg(), extract_gpg_key_comment(), extract_ipv4_from_mapped_ipv6(), fetch_github_gpg_keys(), fetch_github_keys(), fetch_github_ssh_keys(), fetch_gitlab_gpg_keys(), fetch_gitlab_keys(), fetch_gitlab_ssh_keys(), ffmpeg_decoder_create_stdin(), ffmpeg_decoder_create_with_request_options(), ffmpeg_decoder_get_video_dimensions(), ffmpeg_decoder_poll_video(), ffmpeg_decoder_seek_to_timestamp(), ffmpeg_decoder_start_prefetch(), ffmpeg_encoder_create_scaled(), ffmpeg_encoder_write_audio(), ffmpeg_encoder_write_frame(), find_client_by_id(), format_gpg_key_display(), format_ip_with_port(), frame_check_size_overflow(), frame_render_contract_decode(), frame_render_contract_encode(), frame_validate_legacy(), frame_validate_new(), framebuffer_clear(), framebuffer_create(), framebuffer_create_multi(), framebuffer_destroy(), framebuffer_peek_latest_multi_frame(), framebuffer_read_frame(), framebuffer_read_multi_frame(), framebuffer_write_frame(), framebuffer_write_multi_frame(), free_ta_contents(), generate_key_fingerprint(), get_256color_rgb(), get_gpg_fingerprint(), get_gpg_key_id(), get_manpage_template(), gpg_to_x25519_public(), grep_init(), h265_client_capture_and_encode(), h265_client_context_create(), h265_client_init_media_source(), h265_decode(), h265_decoder_create(), h265_encode(), h265_encoder_flush(), h265_server_context_create(), h265_server_decode_and_convert(), h265_server_get_client_decoder(), handle_audio_batch_packet(), handle_audio_opus_batch_packet(), handle_client_leave_packet(), handle_image_frame_packet(), handle_ping_packet(), handle_runtime_settings(), hex_decode(), hex_to_pubkey(), hostname_to_ascii(), http2_connection_create(), http2_connection_next_output(), http2_connection_receive(), http2_connection_submit_response(), http_basic_auth_authorize(), http_basic_auth_matches(), http_basic_auth_parse(), http_render_result_add_file_frame(), http_render_result_add_text_frame(), http_renderer_cancel(), http_renderer_init(), http_renderer_job_start(), http_renderer_render_file(), http_renderer_submit(), http_request_cancel(), http_response_finish(), http_response_retain(), http_response_set_header(), http_response_set_status(), http_response_write(), http_server_adopt_socket(), http_server_authorize(), http_server_dispatch_http3(), http_server_http3_ack(), http_server_http3_create(), http_server_http3_read(), http_server_http3_write(), http_server_http3_wrote(), http_server_init(), http_server_run(), http_server_start(), http_server_wakeup(), https_get(), ice_add_remote_candidate(), ice_format_candidate(), ice_gather_candidates(), image_calc_pixel_buffer_size(), image_calc_pixel_count(), image_calc_rgb_size(), image_calc_total_allocation(), image_clear(), image_new_copy(), image_resize(), image_resize_interpolation(), image_validate_buffer_size(), image_validate_dimensions(), initialize_client_palette(), ipv4_to_ipv6_mapped(), is_session_string(), is_valid_ipv4(), is_valid_ipv6(), key_fingerprint_digest(), key_identity_format(), keyboard_help_is_active(), keymask_render(), kitty_image_write(), log_enable_mmap_sized(), log_mmap_init(), log_net_message(), log_search_filter_buffer(), log_search_init(), log_search_insert_text(), log_set_format(), log_template_free(), main(), manpage_merger_generate_synopsis(), manpage_merger_generate_usage(), manpage_parser_parse_file(), manpage_parser_parse_memory(), manpage_resources_load(), mcp_download_finalize(), mcp_request_parse(), mcp_server_main(), mcp_stdio_reserve(), media_input_normalize(), media_playlist_append(), media_playlist_format(), media_playlist_parse(), media_source_create_interruptible(), media_source_seek(), media_source_start_video(), mirror_convert_frame(), mixer_create_channels(), named_registry_for_each(), named_registry_try_snapshot(), nat_detect_quality(), nat_upnp_get_address(), nat_upnp_get_endpoint(), nat_upnp_open_protocol(), nat_upnp_refresh(), negotiate_determine_result(), network_client_negotiate(), network_connection_adopt(), network_connection_adopt_negotiating(), network_connection_establish(), network_connection_open(), network_connection_prepare_security(), network_connection_run(), network_error_decode(), network_negotiation_receive(), network_server_create(), network_server_run(), network_server_start(), network_server_stop(), openpgp_base64_decode(), openpgp_extract_ed25519_from_mpi(), openpgp_parse_armored_pubkey(), openpgp_parse_armored_seckey(), openpgp_parse_binary_pubkey(), openpgp_parse_binary_seckey(), openpgp_parse_packet_header(), openpgp_parse_public_key_packet(), openpgp_parse_secret_key_packet(), options_apply_patch(), options_builder_generate_manpage_template(), options_collect_identity_keys(), options_config_generate_final_manpage(), options_config_generate_manpage_merged(), options_config_generate_manpage_template(), options_init(), options_json_parse_value(), options_json_schema_for_option(), options_prepare_patch(), options_preset_unified(), options_read_snapshot(), options_registry_add_all_to_builder(), options_registry_find_by_name(), options_registry_find_by_short(), options_registry_get_binary_options(), options_registry_get_enum_values(), options_registry_get_examples(), options_registry_get_for_display(), options_registry_get_for_mode(), options_registry_get_input_type(), options_registry_get_metadata(), options_registry_get_numeric_range(), options_state_init(), options_state_set(), opus_codec_create_decoder_channels(), opus_codec_create_encoder_channels(), opus_codec_decode(), opus_codec_encode(), opus_codec_get_bitrate(), opus_codec_set_bitrate(), opus_codec_set_dtx(), OpusCodecBinding::OpusCodecBinding(), packet_decode_frame_data_buffer(), packet_decode_frame_data_workspace(), packet_decoder_feed(), packet_decrypt_envelope(), packet_encode(), packet_header_build(), packet_parse_error_message(), packet_parse_opus_batch(), packet_parse_remote_log(), packet_queue_create_config(), packet_queue_push_copy(), packet_queue_push_shared(), packet_queue_push_take(), packet_receive(), packet_receive_via_transport(), packet_send(), packet_send_error(), packet_send_remote_log(), packet_send_via_transportv(), packet_validate(), packet_validate_frame_dimensions(), parallel_connect(), parse_address_with_optional_port(), parse_gpg_key(), parse_gpg_key_binary(), parse_gpg_keys_from_response(), parse_hex_color(), parse_int32(), parse_ip_with_port(), parse_keys_from_file(), parse_long(), parse_manpage_sections(), parse_numeric_socket_address(), parse_port(), parse_private_key(), parse_public_key(), parse_public_keys(), parse_ssh_ed25519_line(), parse_ssh_keys_from_response(), parse_ssh_private_key(), parse_uint32(), parse_ulong(), parse_ulonglong(), patch_options(), path_validate_user_path(), peer_crypto_create(), peer_crypto_quic_begin(), peer_crypto_receive(), peer_crypto_send(), peer_crypto_tick(), PeerCryptoBinding::PeerCryptoBinding(), platform_event_listen(), platform_event_loop_create(), platform_event_loop_post(), platform_event_loop_run(), platform_event_loop_tick(), platform_event_loop_work(), platform_event_stream_adopt(), platform_event_stream_deadline(), platform_event_stream_peer(), platform_event_stream_resume(), platform_event_stream_start(), platform_event_stream_work(), platform_event_stream_write(), precalc_rgb_palettes(), private_key_to_x25519(), AudioProcessorBinding::process(), process_decrypted_packet(), prompt_unknown_host(), prompt_unknown_host_no_identity(), public_key_to_x25519(), quantize_color(), quic_accept(), quic_connect(), quic_connection_allow_media(), quic_connection_clear_receiver(), quic_connection_enable_security(), quic_connection_finish_stream(), quic_connection_handle_expiry(), quic_connection_matches_cid(), quic_connection_migrate(), quic_connection_packet_sent(), quic_connection_peer_address(), quic_connection_receive(), quic_connection_server_create(), quic_connection_server_create_validated(), quic_connection_set_receiver(), quic_connection_submit(), quic_connection_submit_datagram(), quic_connection_validate_datagram(), quic_connection_write(), quic_connection_write_close(), quic_datagram_fragment(), quic_datagram_read(), quic_endpoint_address(), quic_endpoint_destroy(), quic_endpoint_migrate(), quic_endpoint_open(), quic_endpoint_set_http_server(), quic_endpoint_stop(), quic_release(), quic_stream_finish(), quic_stream_preamble(), quic_stream_read(), quic_tls_client_configure(), quic_tls_client_create(), quic_tls_server_create(), quic_tls_session_create(), quic_tls_verify_ready(), quic_transport_allow_media(), quic_transport_attach_on_lane(), quic_transport_attach_on_lane_with_waker(), quic_transport_attach_serialized(), quic_transport_begin_security(), quic_transport_destroy_unclaimed_on_lane(), quic_transport_fail(), quic_transport_fail_on_lane(), quic_transport_peer_address(), quic_transport_set_waker(), quic_transport_set_waker_on_lane(), quic_transport_wait_security(), quic_udp_close_peer(), quic_udp_connect(), quic_udp_endpoint_address(), quic_udp_endpoint_create(), quic_udp_migrate(), quic_udp_pump(), quic_udp_remove(), quic_udp_wait(), quic_udp_wait_parameters(), quic_udp_wake(), quic_worker_stop(), rate_limiter_check(), rate_limiter_prune(), rate_limiter_record(), receive_packet_secure_with_timeout(), recv_with_timeout(), registry_entry_applies_to_mode(), registry_find_entry_by_name(), registry_validate_unique_options(), remove_client(), remove_known_host(), TestPatternBinding::render(), render_file_create(), render_file_destroy(), render_file_write_frame(), MirrorFrameBinding::renderAudio(), RendererSessionBinding::RendererSessionBinding(), rgb_to_ansi_8bit(), ringbuffer_create(), safe_parse_audio_message(), safe_parse_size_message(), sdp_detect_terminal_capabilities(), sdp_generate_answer(), sdp_generate_offer(), sdp_get_selected_video_codec(), sdp_parse(), send_crypto_capabilities_packet(), send_crypto_parameters_packet(), send_error_packet_message(), send_image_frame_packet(), send_packet_secure(), send_protocol_version_packet(), send_server_state_to_client(), session_audio_add_source(), session_audio_start_capture(), session_audio_start_duplex(), session_audio_start_playback(), session_audio_write_playback(), session_audio_write_source(), session_capture_create(), session_capture_process_for_transmission_into(), session_client_like_run(), session_connection_establish(), session_connection_start(), session_connection_stop(), session_consensus_create(), session_consensus_get_elected_host(), session_consensus_on_collection_start(), session_consensus_on_election_result(), session_consensus_on_stats_update(), session_consensus_process(), session_consensus_set_topology(), session_display_create(), session_display_destroy(), session_display_encode_frame(), session_display_get_caps(), session_display_get_luminance_palette(), session_display_get_palette_chars(), session_display_get_palette_len(), session_display_get_stdin_reader(), session_display_get_tty_fd(), session_display_has_audio_playback(), session_display_has_tty(), session_display_init_render_file(), session_display_render_frame(), session_display_set_snapshot_actual_duration(), session_display_set_stdin_reader(), session_display_write_ascii_frame(), session_display_write_audio(), session_display_write_raw(), session_host_accept_peer(), session_host_add_client(), session_host_add_memory_participant(), session_host_broadcast_frame(), session_host_create(), session_host_find_client(), session_host_inject_audio(), session_host_inject_frame(), session_host_receive_packet(), session_host_remove_client(), session_host_render_audio(), session_host_render_video(), session_host_send_frame(), session_host_set_client_transport(), session_host_set_display(), session_host_set_render_target(), session_host_start(), session_host_start_render(), session_host_stop_render(), session_mirror_capture_create(), session_participant_connect(), session_participant_create(), session_participant_get_settings(), session_participant_receive_settings(), session_participant_request_settings(), session_participant_set_connection(), session_participant_set_transport(), session_participant_start_audio(), session_participant_start_video(), session_participant_take_connection(), session_pipeline_create(), session_pipeline_destroy(), session_pipeline_run_main(), session_protocol_dispatch(), session_protocol_update_settings(), session_quic_listeners_close(), session_quic_listeners_open(), session_render_loop(), session_server_like_mdns_advertise(), session_server_like_run(), session_settings_from_options(), set_socket_keepalive(), set_socket_nonblocking(), set_socket_timeout(), signaling_broadcast(), signaling_relay_ice(), signaling_relay_sdp(), simple_frame_swap_destroy(), simple_frame_swap_get(), simple_frame_swap_update(), spectral_create(), spectral_process(), ssh_agent_add_key(), ssh_agent_sign(), start_transport_client_threads(), stats_runtime_start(), stats_sampler_create(), stats_sampler_update(), stats_scope_create(), stats_scope_snapshot(), stdout_writer_write(), stop_client_render_threads(), MirrorFrameBinding::submitAudio(), tcp_server_init(), tcp_server_run(), term_renderer_create(), term_renderer_feed(), term_renderer_set_zalgo(), terminal_fd_reader_create(), terminal_fd_reader_next(), terminal_fd_writer_create(), terminal_fd_writer_write(), test_pattern_create(), test_pattern_render_at(), test_pattern_resize(), thread_pool_create(), thread_pool_create_with_workers(), thread_pool_interrupt_all(), thread_pool_queue_work(), thread_pool_spawn(), thread_pool_stop_all(), threaded_send_audio_batch_packet(), threaded_send_audio_opus(), threaded_send_audio_opus_batch(), threaded_send_image_frame(), threaded_send_image_frame_encoded(), threaded_send_packet(), time_format_now(), time_format_safe(), time_timespec_to_ns(), timer_start(), timer_stop(), timer_system_init(), MirrorFrameBinding::transform(), tui_shortcut_help(), turn_generate_credentials(), ui_buttons_key(), ui_buttons_render(), ui_controller_printf(), ui_controller_start_terminal(), ui_controller_title_start(), ui_controller_write(), ui_help_keys(), ui_help_menu_measure(), ui_help_menu_render(), ui_input_edit_key(), ui_input_insert(), ui_input_media_begin(), ui_input_media_take(), ui_input_password(), ui_input_render(), ui_input_take_paste(), ui_input_timeout_report(), ui_layout_measure(), ui_mdns_query(), ui_notice_present(), ui_notice_present_first_use(), ui_output_printf(), ui_output_write(), ui_password_prompt_present(), ui_popup_frame(), ui_popup_frame_titled(), ui_popup_render(), ui_popup_rule(), ui_progress_format(), ui_prompt_present_kind(), ui_scrollbar_cell(), ui_scrollbar_render(), ui_session_context_help_render(), ui_session_help_render(), ui_session_media(), ui_session_resize(), ui_spinner_render(), ui_status_gather(), ui_sync_start(), ui_table_render(), ui_table_row(), ui_text_cell(), ui_text_color_prefix(), ui_text_values_style(), ui_viewport_key(), ui_viewport_update(), update_check_load_cache(), update_check_perform(), update_check_save_cache(), url_is_tcp(), url_is_tcp_scheme(), url_is_websocket(), url_is_websocket_scheme(), url_looks_like_tcp(), url_looks_like_websocket(), url_parse(), url_parts_destroy(), utf8_char_count(), utf8_is_ascii_only(), utf8_is_valid(), utf8_next_char_bytes(), utf8_palette_create(), utf8_strcasestr(), utf8_to_codepoints(), validate_glyph_palette(), validate_gpg_key_format(), validate_key_security(), validate_options_and_report(), validate_palette_chars(), validate_port_callback(), validate_private_key(), validate_public_key(), validate_ssh_key_file(), validate_ssh_key_format(), validate_x25519_key_format(), video_encoder_create(), video_frame_begin_write(), video_frame_buffer_create(), video_frame_buffer_destroy(), video_frame_commit(), video_frame_get_latest(), video_frame_get_stats(), webcam_get_dimensions(), webcam_init_context(), webcam_list_devices(), webcam_read_context(), webrtc_add_remote_candidate(), webrtc_close_datachannel(), webrtc_close_peer_connection(), webrtc_create_datachannel(), webrtc_create_offer(), webrtc_create_peer_connection(), webrtc_datachannel_destroy(), webrtc_datachannel_get_buffered_amount(), webrtc_datachannel_get_label(), webrtc_datachannel_get_max_message_size(), webrtc_datachannel_is_open(), webrtc_datachannel_send(), webrtc_datachannel_set_callbacks(), webrtc_datachannel_set_open_state(), webrtc_get_rtc_id(), webrtc_peer_connection_close(), webrtc_peer_connection_destroy(), webrtc_peer_manager_connect(), webrtc_peer_manager_create(), webrtc_peer_manager_dispatch_ready(), webrtc_peer_manager_handle_ice(), webrtc_peer_manager_handle_sdp(), webrtc_peer_manager_remove_peer(), webrtc_set_remote_description(), webrtc_turn_servers_parse(), websocket_server_init(), websocket_server_run(), websocket_transport_send(), yt_dlp_extract_with_options(), and zalgo_apply().

◆ SET_ERRNO_SYS

#define SET_ERRNO_SYS ( code,
... )
Value:
({ \
int _asciichat_saved_errno = platform_get_last_error(); \
errno_set_with_system_error_and_message((code), __FILE__, __LINE__, __func__, _asciichat_saved_errno, \
__VA_ARGS__); \
})
int platform_get_last_error(void)
Get the last system error code.

Definition at line 134 of file asciichat_errno.h.

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 })

Referenced by accept_with_timeout(), acds_identity_load(), acds_identity_save(), acip_tcp_transport_create(), acip_websocket_server_transport_create(), add_known_host(), colorscheme_export_scheme(), config_create_default(), discovery_keys_clear_cache(), discovery_keys_save_cached(), get_manpage_template(), manpage_parser_parse_memory(), options_config_generate_manpage_template(), packet_receive(), parse_manpage_sections(), remove_known_host(), send_with_timeout(), set_socket_keepalive(), set_socket_nonblocking(), set_socket_timeout(), socket_configure_buffers(), ssh_agent_add_key(), stdout_writer_write(), terminal_fd_reader_create(), terminal_fd_writer_create(), ui_controller_title_start(), ui_output_write(), and ui_sync_start().

Enumeration Type Documentation

◆ asciichat_errno_outcome_t

Enumerator
ASCIICHAT_ERRNO_HANDLED 
ASCIICHAT_ERRNO_DISMISSED 
ASCIICHAT_ERRNO_THREAD_EXIT 
ASCIICHAT_ERRNO_OVERFLOW 

Definition at line 68 of file asciichat_errno.h.

Function Documentation

◆ asciichat_error_format()

const char * asciichat_error_format ( const char * message,
asciichat_error_t code )

Format "message: description (code=N)"; NULL/empty message returns only "description (code=N)". Allocation-free and thread-local; the returned string survives the next seven calls on this thread. Copy it for longer storage. Message text is limited to ASCIICHAT_ERRNO_MESSAGE_MAX-1 bytes; the code and meaning are retained. An existing matching suffix is not duplicated. This is plain text: use SET_ERRNO(code, "%s", formatted), never pass formatted text as the printf format. SET_ERRNO already logs code/meaning automatically, so callers normally supply only their contextual message.

Definition at line 162 of file asciichat_errno.c.

162 {
163 static PLATFORM_THREAD_LOCAL char buffers[ERROR_RENDER_SLOT_COUNT]
165 static PLATFORM_THREAD_LOCAL unsigned next;
166 char *output = buffers[next++ % 8];
168 snprintf(suffix, sizeof(suffix), "%s (code=%d)", asciichat_error_string(code), code);
169 if (!message || !*message || !strcmp(message, asciichat_error_string(code))) {
170 snprintf(output, sizeof(buffers[0]), "%s", suffix);
171 } else {
172 size_t length = strlen(message);
173 size_t suffix_length = strlen(suffix);
174 if (length >= suffix_length && !strcmp(message + length - suffix_length, suffix))
175 snprintf(output, sizeof(buffers[0]), "%s", message);
176 else {
177 size_t limit = length < ASCIICHAT_ERRNO_MESSAGE_MAX ? length : ASCIICHAT_ERRNO_MESSAGE_MAX - 1;
178 // Do not cut a UTF-8 character in half when shortening the message.
179 while (limit && ((unsigned char)message[limit] & 0xc0) == 0x80)
180 --limit;
181 snprintf(output, sizeof(buffers[0]), "%.*s: %s", (int)limit, message, suffix);
182 }
183 }
184 return output;
185}
#define ERROR_RENDER_SLOT_COUNT
#define ASCIICHAT_ERRNO_SUFFIX_BUFFER_SIZE
#define ASCIICHAT_ERRNO_MESSAGE_MAX

References ASCIICHAT_ERRNO_MESSAGE_MAX, ASCIICHAT_ERRNO_SUFFIX_BUFFER_SIZE, ERROR_RENDER_SLOT_COUNT, and error_thread::next.

Referenced by acds_on_host_announcement_ex(), acds_send_current_host(), acip_handle_server_packet(), acip_send_image_frame_h265(), acip_server_receive_and_dispatch(), asciichat_fatal_with_context(), capture_init(), discovery_main(), discovery_session_start(), h265_client_init_media_source(), handle_audio_batch_packet(), handle_audio_opus_batch_packet(), handle_audio_opus_packet(), handle_audio_packet(), handle_image_frame_h265_packet(), log_named_format_or_original(), main(), media_source_create_interruptible(), media_source_seek(), mirror_main(), mixer_add_source(), render_file_create(), session_display_create(), session_display_encode_frame(), session_display_init_render_file(), session_display_render_frame(), session_display_write_ascii_frame(), session_render_loop(), splash_wait_for_animation(), and video_frame_buffer_create().

◆ asciichat_error_stats_get()

asciichat_error_stats_t asciichat_error_stats_get ( void )

Definition at line 774 of file asciichat_errno.c.

774 {
775 registry_lock();
776 asciichat_error_stats_t stats = g_stats;
777 registry_unlock();
778 return stats;
779}

Referenced by asciichat_error_stats_print().

◆ asciichat_error_stats_init()

void asciichat_error_stats_init ( void )

Definition at line 763 of file asciichat_errno.c.

763 {
764 registry_lock();
765 initialize_locked();
766 registry_unlock();
767}

◆ asciichat_error_stats_print()

void asciichat_error_stats_print ( void )

Definition at line 788 of file asciichat_errno.c.

788 {
790 log_plain("Errors: total=%" PRIu64 " pending=%zu threads=%zu dropped=%" PRIu64 " history_overwritten=%" PRIu64,
792 stats.overwritten_history);
793 for (size_t i = 1; i < ARRAY_SIZE(stats.error_counts); ++i)
794 if (stats.error_counts[i])
795 log_plain(" %s: %" PRIu64, asciichat_error_string((asciichat_error_t)i), stats.error_counts[i]);
796}
asciichat_error_stats_t asciichat_error_stats_get(void)
#define ARRAY_SIZE(arr)
Calculate the number of elements in an array.
Definition common.h:180
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
#define log_plain(...)
Plain logging - writes to both log file and stderr without timestamps or log levels.
Definition log/log.h:665

References ARRAY_SIZE, asciichat_error_stats_get(), asciichat_error_stats_t::dropped_errors, asciichat_error_stats_t::error_counts, log_plain, asciichat_error_stats_t::overwritten_history, asciichat_error_stats_t::pending_errors, asciichat_error_stats_t::registered_threads, and asciichat_error_stats_t::total_errors.

Referenced by debug_stats_print(), errno_print_stacks(), and stats_logger_thread().

◆ asciichat_error_stats_record()

void asciichat_error_stats_record ( asciichat_error_t code)

Definition at line 768 of file asciichat_errno.c.

768 {
769 uint64_t timestamp = time_ns_to_us(time_get_realtime_ns());
770 registry_lock();
771 record_stats_locked(code, timestamp);
772 registry_unlock();
773}
unsigned long long uint64_t
Definition common.h:63

◆ asciichat_error_stats_reset()

void asciichat_error_stats_reset ( void )

Definition at line 780 of file asciichat_errno.c.

780 {
781 registry_lock();
782 size_t pending = g_stats.pending_errors, threads = g_stats.registered_threads;
783 memset(&g_stats, 0, sizeof(g_stats));
784 g_stats.pending_errors = pending;
785 g_stats.registered_threads = threads;
786 registry_unlock();
787}

◆ asciichat_fatal_with_context()

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

Definition at line 884 of file asciichat_errno.c.

885 {
886 // This path must also work when an allocator or a diagnostic itself failed.
887 bool previous = g_recording;
888 g_recording = true;
889 char message[ASCIICHAT_ERRNO_MESSAGE_MAX];
890 va_list args;
891 va_start(args, format);
892 vsnprintf(message, sizeof(message), format ? format : "", args);
893 va_end(args);
894 NOTICE(FATAL, "FATAL ERROR", "%s", asciichat_error_format(message, code));
895 log_error("Fatal: %s (at %s:%d in %s)", asciichat_error_format(message, code), file ? file : "?", line,
896 function ? function : "?");
898 g_recording = previous;
899#ifdef EMSCRIPTEN_BUILD
900 SET_ERRNO(code, "%s", message);
901#else
902 exit(code);
903#endif
904}
action_args_t args
Definition actions.c:78
const char * asciichat_error_format(const char *message, asciichat_error_t code)
void errno_print_stacks(void)
#define SET_ERRNO(code,...)
#define FATAL(code,...)
Exit with error code and custom message, with stack trace in debug builds.
Definition common.h:160
#define log_error(...)
Log an ERROR message.
Definition log/log.h:634
#define NOTICE(severity, title,...)
Definition notice.h:68

◆ asciichat_print_error_context()

void asciichat_print_error_context ( const asciichat_error_context_t * context)

Definition at line 829 of file asciichat_errno.c.

829 {
830 print_error_context(context, true);
831}

Referenced by errno_print_stacks().

◆ errno_checkpoint()

◆ errno_clear()

void errno_clear ( void )

Definition at line 615 of file asciichat_errno.c.

615 {
616 clear_thread(thread_current_id(), false);
618}
void platform_clear_error_state(void)

References platform_clear_error_state().

◆ errno_clear_all()

void errno_clear_all ( void )

Definition at line 619 of file asciichat_errno.c.

619 {
620 clear_thread(thread_current_id(), true);
622}

References platform_clear_error_state().

Referenced by browser_error_dismiss().

◆ errno_clear_if_current()

bool errno_clear_if_current ( uint64_t thread_id,
uint64_t generation,
uint64_t error_id )

Clear one displayed pending frame when its thread generation and ID still match.

Definition at line 634 of file asciichat_errno.c.

634 {
635 registry_lock();
636 uint64_t now = time_get_ns();
637 error_thread_t *thread = find_thread(id);
638 int previous = NO_FRAME;
639 int index = thread ? thread->top : NO_FRAME;
640 while (index != NO_FRAME && g_frames[index].context.error_id != error_id) {
641 previous = index;
642 index = g_frames[index].next;
643 }
644 bool matches = thread && thread->generation == generation && index != NO_FRAME;
645 if (matches) {
646 if (previous == NO_FRAME)
647 thread->top = g_frames[index].next;
648 else
649 g_frames[previous].next = g_frames[index].next;
650 --thread->depth;
651 release_frame_locked(index, ASCIICHAT_ERRNO_HANDLED, now);
652 }
653 registry_unlock();
654 return matches;
655}
#define NO_FRAME
struct error_thread error_thread_t
For error thread, this is the live record that ties id, generation, top, depth together....
static bool size_t index
Definition queries.h:8
uint64_t generation

References ASCIICHAT_ERRNO_HANDLED, error_thread::depth, asciichat_error_context_t::error_id, error_thread::generation, index, NO_FRAME, and error_thread::top.

Referenced by ui_errno_stacks_handle_key().

◆ errno_clear_if_top()

bool errno_clear_if_top ( uint64_t thread_id,
uint64_t generation,
uint64_t error_id )

Definition at line 623 of file asciichat_errno.c.

623 {
624 registry_lock();
625 uint64_t now = time_get_ns();
626 error_thread_t *thread = find_thread(id);
627 bool matches =
628 thread && thread->generation == generation && thread->depth && g_frames[thread->top].context.error_id == error_id;
629 if (matches)
630 pop_locked(thread, ASCIICHAT_ERRNO_HANDLED, now);
631 registry_unlock();
632 return matches;
633}

References ASCIICHAT_ERRNO_HANDLED, error_thread::depth, error_thread::generation, and error_thread::top.

◆ errno_clear_thread_error()

void errno_clear_thread_error ( uint64_t thread_id)

Definition at line 609 of file asciichat_errno.c.

609 {
610 clear_thread(id, false);
611}

◆ errno_clear_thread_errors()

void errno_clear_thread_errors ( uint64_t thread_id)

Definition at line 612 of file asciichat_errno.c.

612 {
613 clear_thread(id, true);
614}

◆ errno_destroy()

void errno_destroy ( void )

Definition at line 727 of file asciichat_errno.c.

727 {
728 uint64_t now = time_get_ns();
729 uint64_t id = thread_current_id();
730 registry_lock();
731#ifndef EMSCRIPTEN_BUILD
732 if (g_tls_ready)
733 platform_tls_set(g_tls_key, NULL);
734#endif
735 error_thread_t *thread = find_thread(id);
736 if (thread)
737 unregister_locked(thread, now);
738 registry_unlock();
739}

Referenced by asciichat_shared_destroy(), client_cleanup(), errno_shutdown(), and mirror_cleanup().

◆ errno_exit_code()

asciichat_error_t errno_exit_code ( void )

Definition at line 937 of file asciichat_errno.c.

937 {
938 registry_lock();
939 asciichat_error_t code = g_exit_code;
940 registry_unlock();
941 return code;
942}

Referenced by main().

◆ errno_get()

asciichat_error_t errno_get ( void )

Definition at line 533 of file asciichat_errno.c.

533 {
534 return errno_get_thread_error(thread_current_id());
535}
asciichat_error_t errno_get_thread_error(uint64_t id)

References errno_get_thread_error().

◆ errno_get_thread_error()

asciichat_error_t errno_get_thread_error ( uint64_t thread_id)

Definition at line 526 of file asciichat_errno.c.

526 {
527 registry_lock();
528 error_thread_t *thread = find_thread(id);
529 asciichat_error_t code = thread && thread->depth ? g_frames[thread->top].context.code : ASCIICHAT_OK;
530 registry_unlock();
531 return code;
532}
@ ASCIICHAT_OK
Definition error_codes.h:46

References ASCIICHAT_OK, error_thread::depth, and error_thread::top.

Referenced by errno_get().

◆ errno_has()

bool errno_has ( asciichat_error_context_t * context)

Definition at line 523 of file asciichat_errno.c.

523 {
524 return errno_has_thread_error(thread_current_id(), context);
525}
bool errno_has_thread_error(uint64_t id, asciichat_error_context_t *context)

References errno_has_thread_error().

◆ errno_has_code()

bool errno_has_code ( asciichat_error_t code)

Definition at line 559 of file asciichat_errno.c.

559 {
560 return errno_has_code_tid(thread_current_id(), code);
561}

References errno_has_code_tid().

◆ errno_has_code_since()

bool errno_has_code_since ( asciichat_errno_scope_t scope,
asciichat_error_t code )

Definition at line 562 of file asciichat_errno.c.

562 {
563 registry_lock();
564 error_thread_t *thread = find_thread(scope.thread_id);
565 bool found = thread && thread->generation == scope.generation && has_code_locked(thread, scope.after_id, code);
566 registry_unlock();
567 return found;
568}

References asciichat_errno_scope_t::after_id, asciichat_errno_scope_t::generation, error_thread::generation, and asciichat_errno_scope_t::thread_id.

◆ errno_has_code_tid()

bool errno_has_code_tid ( uint64_t thread_id,
asciichat_error_t code )

Definition at line 553 of file asciichat_errno.c.

553 {
554 registry_lock();
555 bool found = has_code_locked(find_thread(id), 0, code);
556 registry_unlock();
557 return found;
558}

Referenced by errno_has_code().

◆ errno_has_thread_error()

bool errno_has_thread_error ( uint64_t thread_id,
asciichat_error_context_t * context )

Definition at line 510 of file asciichat_errno.c.

510 {
511 registry_lock();
512 error_thread_t *thread = find_thread(id);
513 bool found = thread && thread->depth;
514 if (context) {
515 if (found)
516 *context = g_frames[thread->top].context;
517 else
518 memset(context, 0, sizeof(*context));
519 }
520 registry_unlock();
521 return found;
522}

References error_thread::depth, and error_thread::top.

Referenced by errno_has().

◆ errno_has_wsa_error()

bool errno_has_wsa_error ( void )

Definition at line 536 of file asciichat_errno.c.

536 {
538 return HAS_ERRNO(&context) && context.has_wsa_error;
539}

References HAS_ERRNO, and asciichat_error_context_t::has_wsa_error.

◆ errno_history_snapshot()

size_t errno_history_snapshot ( asciichat_errno_history_t * out,
size_t capacity )

Definition at line 714 of file asciichat_errno.c.

714 {
715 registry_lock();
716 size_t count = g_history_count;
717 if (out)
718 for (size_t i = 0; i < count && i < capacity; ++i)
719 out[i] = g_history[(g_history_next + ASCIICHAT_ERRNO_HISTORY_SIZE - 1 - i) % ASCIICHAT_ERRNO_HISTORY_SIZE];
720 registry_unlock();
721 return count;
722}
#define ASCIICHAT_ERRNO_HISTORY_SIZE
static bool size_t gotel_query_t * out
Definition queries.h:8

References ASCIICHAT_ERRNO_HISTORY_SIZE, and out.

Referenced by errno_print_history().

◆ errno_import()

asciichat_error_t errno_import ( const asciichat_error_context_t * cause)

Import an owned value snapshot into the caller's stack, linking to its original ID. Synchronization of snapshot transfer belongs to the operation owner.

Definition at line 580 of file asciichat_errno.c.

580 {
581 if (!cause || cause->code == ASCIICHAT_OK)
582 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing failure snapshot");
583 if (g_recording)
584 return cause->code;
585 g_recording = true;
586 asciichat_error_context_t copy = *cause;
587 copy.cause_id = cause->error_id;
588 copy.thread_id = thread_current_id();
589 copy.timestamp = time_ns_to_us(time_get_realtime_ns());
590 copy.created_ns = time_get_ns();
591 copy.backtrace.symbols = NULL;
592 copy.backtrace.tried_symbolize = false;
593 push_context(&copy);
594 g_recording = false;
595 return copy.code;
596}
@ ERROR_INVALID_PARAM
uint64_t created_ns
Monotonic time, for age.
uint64_t timestamp
Microseconds since epoch, for logs.

References ASCIICHAT_OK, asciichat_error_context_t::backtrace, asciichat_error_context_t::cause_id, asciichat_error_context_t::code, asciichat_error_context_t::created_ns, asciichat_error_context_t::error_id, ERROR_INVALID_PARAM, SET_ERRNO, asciichat_error_context_t::thread_id, and asciichat_error_context_t::timestamp.

Referenced by ffmpeg_decoder_read_video_frame(), http_renderer_render_file(), and session_pipeline_destroy().

◆ errno_notifications_dismiss()

void errno_notifications_dismiss ( uint64_t through_id)

Definition at line 136 of file asciichat_errno.c.

136 {
137 registry_lock();
138 if (through_id > g_title_dismissed_through)
139 g_title_dismissed_through = through_id;
140 while (g_notification_count && g_notifications[g_notification_first].error_id <= through_id) {
141 memset(&g_notifications[g_notification_first], 0, sizeof(g_notifications[0]));
142 g_notification_first = (g_notification_first + 1) % ASCIICHAT_ERRNO_HISTORY_SIZE;
143 --g_notification_count;
144 }
145 g_notification_dropped = 0;
146 atomic_store_bool_impl(&g_notifications_pending, g_notification_count != 0);
147 registry_unlock();
148}

References ASCIICHAT_ERRNO_HISTORY_SIZE.

Referenced by ui_error_popup_key().

◆ errno_notifications_enable()

void errno_notifications_enable ( bool enabled)

Independent, bounded UI notifications. Acknowledgment never changes pending stacks. Enabling starts a fresh terminal session; repeated enable calls preserve the batch. Snapshots are oldest-first. Dismiss only through the last displayed ID so concurrent arrivals remain visible. No callbacks, allocation, or symbolization run on producers.

Definition at line 94 of file asciichat_errno.c.

94 {
95 registry_lock();
96 if (!enabled || (!g_notifications_enabled && !g_notifications_paused)) {
97 g_notification_first = g_notification_count = 0;
98 g_notification_dropped = 0;
99 atomic_store_bool_impl(&g_notifications_pending, false);
100 }
101 g_notifications_enabled = enabled;
102 g_notifications_paused = false;
103 registry_unlock();
104}
bool enabled
Is filtering active?
Definition grep.c:62

References enabled.

Referenced by errno_shutdown(), ui_controller_finish(), and ui_controller_shutdown().

◆ errno_notifications_pause()

void errno_notifications_pause ( void )

Stop collecting new notifications while retaining those already queued.

Definition at line 106 of file asciichat_errno.c.

106 {
107 registry_lock();
108 if (g_notifications_enabled) {
109 g_notifications_enabled = false;
110 g_notifications_paused = true;
111 }
112 registry_unlock();
113}

◆ errno_notifications_pending()

bool errno_notifications_pending ( void )

Definition at line 115 of file asciichat_errno.c.

115 {
116 return atomic_load_bool_impl(&g_notifications_pending);
117}

Referenced by ui_error_popup_preserve(), and ui_error_popup_visible().

◆ errno_notifications_snapshot()

size_t errno_notifications_snapshot ( asciichat_error_context_t * out,
size_t capacity,
uint64_t * dropped )

Definition at line 125 of file asciichat_errno.c.

125 {
126 registry_lock();
127 size_t count = MIN(capacity, g_notification_count);
128 for (size_t i = 0; out && i < count; ++i)
129 out[i] = g_notifications[(g_notification_first + i) % ASCIICHAT_ERRNO_HISTORY_SIZE];
130 if (dropped)
131 *dropped = g_notification_dropped;
132 registry_unlock();
133 return count;
134}
#define MIN(a, b)
Return the minimum of two values.
Definition common.h:170

References ASCIICHAT_ERRNO_HISTORY_SIZE, MIN, and out.

Referenced by ui_error_popup_preserve().

◆ errno_notifications_suppress()

bool errno_notifications_suppress ( bool suppress)

Suppress UI notifications on this thread, without suppressing errno storage/logging.

Definition at line 119 of file asciichat_errno.c.

119 {
120 bool previous = g_suppress_notifications;
121 g_suppress_notifications = suppress;
122 return previous;
123}

Referenced by discovery_mdns_query(), discovery_session_create(), nat_detect_quality(), session_server_like_run(), and ui_error_popup_preserve().

◆ errno_peek_since()

bool errno_peek_since ( asciichat_errno_scope_t scope,
asciichat_error_context_t * out )

Copy the newest error belonging to this operation, without consuming it.

Definition at line 570 of file asciichat_errno.c.

570 {
571 registry_lock();
572 error_thread_t *thread = find_thread(scope.thread_id);
573 bool found = thread && thread->generation == scope.generation && thread->top != NO_FRAME &&
574 g_frames[thread->top].context.error_id > scope.after_id;
575 if (found && out)
576 *out = g_frames[thread->top].context;
577 registry_unlock();
578 return found;
579}

References asciichat_errno_scope_t::after_id, asciichat_errno_scope_t::generation, error_thread::generation, NO_FRAME, out, asciichat_errno_scope_t::thread_id, and error_thread::top.

Referenced by action_completions(), capture_init(), ffmpeg_decoder_poll_video(), log_net_message(), session_capture_create(), and session_render_loop().

◆ errno_print_chain()

void errno_print_chain ( uint64_t thread_id,
uint64_t error_id )

Definition at line 914 of file asciichat_errno.c.

914 {
916 size_t count = errno_snapshot(id, frames, ASCIICHAT_ERRNO_MAX_DEPTH).copied;
917 log_plain("Failure chain (outer context -> root cause):");
918 for (size_t i = 0; i < count && error_id; ++i) {
919 if (frames[i].error_id == error_id) {
920 // Automatic error logs keep their full cause metadata at normal verbosity.
921 // Symbolization can launch external tools and is reserved for Debug logs;
922 // explicit stack reports above still include backtraces at every level.
923 print_error_context(&frames[i], log_get_level() <= LOG_DEBUG);
924 error_id = frames[i].cause_id;
925 }
926 }
927 if (error_id)
928 log_plain(" Cause #%" PRIu64 " was resolved or evicted; consult handled-error history", error_id);
929}
asciichat_errno_snapshot_t errno_snapshot(uint64_t id, asciichat_error_context_t *out, size_t capacity)
#define ASCIICHAT_ERRNO_MAX_DEPTH
log_level_t log_get_level(void)
Get the current minimum log level.
Definition log.c:742
#define LOG_DEBUG
Definition types.h:39

References ASCIICHAT_ERRNO_MAX_DEPTH, asciichat_error_context_t::cause_id, asciichat_errno_snapshot_t::copied, errno_snapshot(), LOG_DEBUG, log_get_level(), and log_plain.

◆ errno_print_hash_stats()

void errno_print_hash_stats ( void )

Definition at line 867 of file asciichat_errno.c.

867 {
868 size_t used = 0, max_chain = 0;
869 registry_lock();
870 for (size_t i = 0; i < ERRNO_BUCKETS; ++i) {
871 size_t chain = 0;
872 for (error_thread_t *thread = g_buckets[i]; thread; thread = thread->next)
873 ++chain;
874 used += chain != 0;
875 if (chain > max_chain)
876 max_chain = chain;
877 }
878 size_t entries = g_stats.registered_threads;
879 registry_unlock();
880 log_plain("Error registry: entries=%zu buckets=%d used=%zu max_chain=%zu reserved_bytes=%zu", entries, ERRNO_BUCKETS,
881 used, max_chain, sizeof(g_threads) + sizeof(g_buckets) + sizeof(g_frames) + sizeof(g_history));
882}
#define ERRNO_BUCKETS

References ERRNO_BUCKETS, log_plain, and error_thread::next.

◆ errno_print_history()

void errno_print_history ( void )

Definition at line 856 of file asciichat_errno.c.

856 {
859 static const char *outcomes[] = {"handled", "dismissed", "thread-exit", "overflow"};
860 for (size_t i = 0; i < count; ++i) {
861 const asciichat_errno_history_t *event = &events[i];
862 log_plain("Error #%" PRIu64 " thread=%" PRIu64 " code=%d %s after %.3fms: %s", event->context.error_id,
863 event->context.thread_id, event->context.code, outcomes[event->outcome],
864 (double)(event->resolved_ns - event->context.created_ns) / 1e6, event->context.context_message);
865 }
866}
size_t errno_history_snapshot(asciichat_errno_history_t *out, size_t capacity)

References ASCIICHAT_ERRNO_HISTORY_SIZE, errno_history_snapshot(), and log_plain.

◆ errno_print_stacks()

void errno_print_stacks ( void )

Definition at line 833 of file asciichat_errno.c.

833 {
834 // Copy one bounded thread stack at a time. A generation check prevents a
835 // reused thread slot from being attributed to the thread sampled earlier.
837 size_t count = 0;
838 registry_lock();
839 for (size_t i = 0; i < ASCIICHAT_ERRNO_MAX_THREADS; ++i)
840 if (g_threads[i].depth) {
841 ids[count] = g_threads[i].id;
842 generations[count++] = g_threads[i].generation;
843 }
844 registry_unlock();
845 log_plain("Pending error stacks (%zu threads):", count);
846 for (size_t i = 0; i < count; ++i) {
848 size_t depth = errno_snapshot(ids[i], contexts, ASCIICHAT_ERRNO_MAX_DEPTH).copied;
849 if (!depth || contexts[0].generation != generations[i])
850 continue;
851 for (size_t j = 0; j < depth; ++j)
852 asciichat_print_error_context(&contexts[j]);
853 }
855}
void asciichat_error_stats_print(void)
#define ASCIICHAT_ERRNO_MAX_THREADS

References ASCIICHAT_ERRNO_MAX_DEPTH, ASCIICHAT_ERRNO_MAX_THREADS, asciichat_error_stats_print(), asciichat_print_error_context(), asciichat_errno_snapshot_t::copied, error_thread::depth, errno_snapshot(), error_thread::generation, and log_plain.

Referenced by asciichat_fatal_with_context().

◆ errno_request_exit()

void errno_request_exit ( asciichat_error_t code)

Definition at line 931 of file asciichat_errno.c.

931 {
932 registry_lock();
933 if (g_exit_code == ASCIICHAT_OK)
934 g_exit_code = code;
935 registry_unlock();
936}

References ASCIICHAT_OK.

◆ errno_scope_begin()

◆ errno_scope_end()

void errno_scope_end ( asciichat_errno_scope_t scope,
asciichat_errno_outcome_t outcome )

Definition at line 676 of file asciichat_errno.c.

676 {
677 uint64_t now = time_get_ns();
678 // Recovery runs on the offending thread. Cross-thread clearing has separate APIs.
679 if (scope.thread_id != thread_current_id())
680 return;
681 registry_lock();
682 error_thread_t *thread = find_thread(scope.thread_id);
683 if (thread && thread->generation == scope.generation) {
684 while (thread->depth && g_frames[thread->top].context.error_id > scope.after_id)
685 pop_locked(thread, outcome, now);
686 thread->cause_after_id = scope.previous_after_id;
687 }
688 registry_unlock();
689}
uint64_t cause_after_id

References asciichat_errno_scope_t::after_id, error_thread::cause_after_id, error_thread::depth, asciichat_errno_scope_t::generation, error_thread::generation, asciichat_errno_scope_t::previous_after_id, asciichat_errno_scope_t::thread_id, and error_thread::top.

Referenced by acip_settings_request(), asciichat_mdns_advertise(), audio_start_duplex(), browser_security_packet(), config_load_and_apply(), config_load_system_and_user(), discovery_mdns_query(), discovery_session_create(), ffmpeg_decoder_create_with_request_options(), main(), media_source_create_interruptible(), nat_detect_quality(), nat_upnp_open_protocol(), process_decrypted_packet(), session_connection_establish(), session_participant_connect(), session_server_like_run(), ui_controller_size(), ui_input_media_take(), and ui_notice_first_use_complete().

◆ errno_scope_is_clean()

bool errno_scope_is_clean ( asciichat_errno_scope_t scope)

Definition at line 906 of file asciichat_errno.c.

906 {
907 registry_lock();
908 error_thread_t *thread = find_thread(scope.thread_id);
909 bool clean = !thread || thread->generation != scope.generation || !thread->depth ||
910 g_frames[thread->top].context.error_id <= scope.after_id;
911 registry_unlock();
912 return clean;
913}

References asciichat_errno_scope_t::after_id, error_thread::depth, asciichat_errno_scope_t::generation, error_thread::generation, asciichat_errno_scope_t::thread_id, and error_thread::top.

◆ errno_set()

asciichat_error_t errno_set ( asciichat_error_t code,
const char * file,
int line,
const char * function,
const char * message )

Definition at line 475 of file asciichat_errno.c.

476 {
477 return errno_set_with_message(code, file, line, function, "%s", message ? message : "");
478}

References errno_set_with_message().

◆ errno_set_with_message()

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

Definition at line 466 of file asciichat_errno.c.

467 {
468 va_list args;
469 va_start(args, format);
470 asciichat_error_t result = set_formatted(code, file, line, function, 0, false, 0, false, format, args);
471 va_end(args);
472 return result;
473}

References args.

Referenced by errno_set().

◆ errno_set_with_system_error()

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

Definition at line 490 of file asciichat_errno.c.

491 {
492 return errno_set_with_system_error_and_message(code, file, line, function, sys_errno, "System operation failed (%d)",
493 sys_errno);
494}
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,...)

References errno_set_with_system_error_and_message().

Referenced by accept_with_timeout(), and recv_with_timeout().

◆ errno_set_with_system_error_and_message()

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,
... )

Definition at line 480 of file asciichat_errno.c.

482 {
483 va_list args;
484 va_start(args, format);
485 asciichat_error_t result = set_formatted(code, file, line, function, sys_errno, true, 0, false, format, args);
486 va_end(args);
487 return result;
488}

References args.

Referenced by errno_set_with_system_error().

◆ errno_set_with_wsa_error()

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

Definition at line 505 of file asciichat_errno.c.

506 {
507 return set_wsa(code, file, line, function, wsa_error, "Socket operation failed (%d)", wsa_error);
508}

◆ errno_shutdown()

void errno_shutdown ( void )

Definition at line 740 of file asciichat_errno.c.

740 {
743 registry_lock();
744 g_shutdown = true;
745 memset(g_threads, 0, sizeof(g_threads));
746 memset(g_buckets, 0, sizeof(g_buckets));
747 memset(g_frames, 0, sizeof(g_frames));
748 memset(g_history, 0, sizeof(g_history));
749 g_history_count = g_history_next = 0;
750 g_stats.pending_errors = g_stats.registered_threads = 0;
751#ifndef EMSCRIPTEN_BUILD
752 bool delete_key = g_tls_ready;
753 tls_key_t key = g_tls_key;
754 g_tls_ready = false;
755#endif
756 registry_unlock();
757#ifndef EMSCRIPTEN_BUILD
758 if (delete_key)
759 platform_tls_key_delete(key);
760#endif
761}
void errno_destroy(void)
void errno_notifications_enable(bool enabled)

References errno_destroy(), and errno_notifications_enable().

Referenced by asciichat_shared_destroy().

◆ errno_snapshot()

asciichat_errno_snapshot_t errno_snapshot ( uint64_t thread_id,
asciichat_error_context_t * out,
size_t capacity )

Copy newest-first up to capacity. The result distinguishes total depth from copied frames.

Definition at line 690 of file asciichat_errno.c.

690 {
691 registry_lock();
692 error_thread_t *thread = find_thread(id);
693 size_t depth = thread ? thread->depth : 0;
694 asciichat_errno_snapshot_t snapshot = {.total = depth};
695 if (thread && out)
696 for (int index = thread->top; index != NO_FRAME && snapshot.copied < capacity; index = g_frames[index].next)
697 out[snapshot.copied++] = g_frames[index].context;
698 registry_unlock();
699 return snapshot;
700}

References asciichat_errno_snapshot_t::copied, error_thread::depth, index, NO_FRAME, out, and error_thread::top.

Referenced by browser_error_snapshot(), errno_print_chain(), errno_print_stacks(), and packet_format_error_stack().

◆ errno_suppress()

void errno_suppress ( bool suppress)

Definition at line 724 of file asciichat_errno.c.

724 {
725 g_suppress_logging = suppress;
726}

◆ errno_threads_snapshot()

size_t errno_threads_snapshot ( uint64_t * out,
size_t capacity )

Copy registered thread IDs. Returns the total count so truncation is visible.

Definition at line 701 of file asciichat_errno.c.

701 {
702 registry_lock();
703 size_t count = 0;
704 for (size_t i = 0; i < ASCIICHAT_ERRNO_MAX_THREADS; ++i) {
705 if (!g_threads[i].generation)
706 continue;
707 if (out && count < capacity)
708 out[count] = g_threads[i].id;
709 ++count;
710 }
711 registry_unlock();
712 return count;
713}

References ASCIICHAT_ERRNO_MAX_THREADS, error_thread::generation, and out.

◆ errno_title_snapshot()

size_t errno_title_snapshot ( asciichat_error_context_t * latest)

Count distinct unacknowledged pending frames and visible notifications, copying the newest. The count and value come from the same synchronized registry snapshot.

Definition at line 207 of file asciichat_errno.c.

207 {
208 asciichat_error_context_t newest = {0};
209 registry_lock();
210 size_t count = 0;
211 for (size_t i = 0; i < ASCIICHAT_ERRNO_MAX_THREADS; ++i) {
212 error_thread_t *thread = &g_threads[i];
213 for (int frame = thread->depth ? thread->top : NO_FRAME; frame != NO_FRAME; frame = g_frames[frame].next) {
214 const asciichat_error_context_t *entry = &g_frames[frame].context;
215 if (entry->error_id <= g_title_dismissed_through)
216 continue;
217 ++count;
218 if (entry->error_id > newest.error_id)
219 newest = *entry;
220 }
221 }
222 for (size_t i = 0; i < g_notification_count; ++i) {
223 const asciichat_error_context_t *entry =
224 &g_notifications[(g_notification_first + i) % ASCIICHAT_ERRNO_HISTORY_SIZE];
225 error_thread_t *thread = find_thread(entry->thread_id);
226 bool pending = false;
227 if (thread && thread->generation == entry->generation) {
228 for (int frame = thread->top; frame != NO_FRAME; frame = g_frames[frame].next) {
229 if (g_frames[frame].context.error_id == entry->error_id) {
230 pending = true;
231 break;
232 }
233 }
234 }
235 if (!pending)
236 ++count;
237 if (entry->error_id > newest.error_id)
238 newest = *entry;
239 }
240 if (latest)
241 *latest = newest;
242 registry_unlock();
243 return count;
244}

References ASCIICHAT_ERRNO_HISTORY_SIZE, ASCIICHAT_ERRNO_MAX_THREADS, error_thread::depth, asciichat_error_context_t::error_id, asciichat_error_context_t::generation, NO_FRAME, asciichat_error_context_t::thread_id, and error_thread::top.