diff --git a/base64.c b/base64.c index c0dfc807..83655dfc 100644 --- a/base64.c +++ b/base64.c @@ -4,12 +4,12 @@ #include #include #include -#include #include #define LOG_MODULE "base64" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" enum { P = 1 << 6, // Padding byte (=) diff --git a/client.c b/client.c index 58a500eb..c78c1f59 100644 --- a/client.c +++ b/client.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -16,6 +15,7 @@ #define LOG_ENABLE_DBG 0 #include "log.h" #include "client-protocol.h" +#include "debug.h" #include "foot-features.h" #include "version.h" #include "xmalloc.h" diff --git a/config.c b/config.c index 06691545..00040802 100644 --- a/config.c +++ b/config.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -21,6 +20,7 @@ #define LOG_MODULE "config" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" #include "input.h" #include "macros.h" #include "tokenize.h" diff --git a/csi.c b/csi.c index 9f246a33..9279345f 100644 --- a/csi.c +++ b/csi.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #if defined(_DEBUG) @@ -16,6 +15,7 @@ #define LOG_ENABLE_DBG 0 #include "log.h" #include "config.h" +#include "debug.h" #include "grid.h" #include "selection.h" #include "sixel.h" diff --git a/debug.c b/debug.c new file mode 100644 index 00000000..03ead23b --- /dev/null +++ b/debug.c @@ -0,0 +1,48 @@ +#include "debug.h" + +#include +#include +#include +#include +#include +#include + +#if defined(__SANITIZE_ADDRESS__) || HAS_FEATURE(address_sanitizer) +#include +#define ASAN_ENABLED 1 +#endif + +static void +print_stack_trace(void) +{ +#ifdef ASAN_ENABLED + fputs("\nStack trace:\n", stderr); + __sanitizer_print_stack_trace(); +#endif +} + +noreturn void +fatal_error(const char *msg, int err) +{ + syslog(LOG_ERR, "%s: %s", msg, strerror(err)); + errno = err; + perror(msg); + print_stack_trace(); + abort(); +} + +noreturn void +bug(const char *file, int line, const char *func, const char *fmt, ...) +{ + fprintf(stderr, "\n%s:%d: BUG in %s(): ", file, line, func); + + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + fputc('\n', stderr); + print_stack_trace(); + fflush(stderr); + abort(); +} diff --git a/debug.h b/debug.h new file mode 100644 index 00000000..ba71c047 --- /dev/null +++ b/debug.h @@ -0,0 +1,32 @@ +#pragma once + +#include "macros.h" + +#ifdef NDEBUG + #define BUG(...) UNREACHABLE() +#else + #define BUG(...) bug(__FILE__, __LINE__, __func__, __VA_ARGS__) +#endif + +#undef assert + +#define assert(x) do { \ + IGNORE_WARNING("-Wtautological-compare") \ + if (unlikely(!(x))) { \ + BUG("assertion failed: '%s'", #x); \ + } \ + UNIGNORE_WARNINGS \ +} while (0) + +#ifndef static_assert + #if __STDC_VERSION__ >= 201112L + #define static_assert(x, msg) _Static_assert((x), msg) + #elif GNUC_AT_LEAST(4, 6) || HAS_EXTENSION(c_static_assert) + #define static_assert(x, msg) __extension__ _Static_assert((x), msg) + #else + #define static_assert(x, msg) + #endif +#endif + +noreturn void fatal_error(const char *msg, int err) COLD; +noreturn void bug(const char *file, int line, const char *func, const char *fmt, ...) PRINTF(4) COLD; diff --git a/fdm.c b/fdm.c index 39a72f5b..d0f9f9d1 100644 --- a/fdm.c +++ b/fdm.c @@ -5,7 +5,6 @@ #include #include #include -#include #include #include @@ -15,6 +14,7 @@ #define LOG_MODULE "fdm" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" struct handler { int fd; diff --git a/grid.c b/grid.c index 9d6ae454..ce691014 100644 --- a/grid.c +++ b/grid.c @@ -1,11 +1,11 @@ #include "grid.h" #include -#include #define LOG_MODULE "grid" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" #include "macros.h" #include "sixel.h" #include "util.h" diff --git a/log.c b/log.c index d47e22ac..2dafd49b 100644 --- a/log.c +++ b/log.c @@ -1,15 +1,15 @@ #include "log.h" -#include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include +#include +#include #include -#include +#include "debug.h" static bool colorize = false; static bool do_syslog = true; diff --git a/macros.h b/macros.h index 1fd82b77..206c18d3 100644 --- a/macros.h +++ b/macros.h @@ -27,6 +27,21 @@ #define HAS_BUILTIN(x) 0 #endif +#ifdef __has_feature + #define HAS_FEATURE(x) __has_feature(x) +#else + #define HAS_FEATURE(x) 0 +#endif + +// __has_extension() is a Clang macro used to determine if a feature is +// available even if not standardized in the current "-std" mode. +#ifdef __has_extension + #define HAS_EXTENSION(x) __has_extension(x) +#else + // Clang versions prior to 3.0 only supported __has_feature() + #define HAS_EXTENSION(x) HAS_FEATURE(x) +#endif + #if GNUC_AT_LEAST(3, 0) || HAS_ATTRIBUTE(unused) || defined(__TINYC__) #define UNUSED __attribute__((__unused__)) #else @@ -139,11 +154,11 @@ #define XSTRDUP XMALLOC NONNULL_ARGS #if __STDC_VERSION__ >= 201112L - #define NORETURN _Noreturn + #define noreturn _Noreturn #elif GNUC_AT_LEAST(3, 0) - #define NORETURN __attribute__((__noreturn__)) + #define noreturn __attribute__((__noreturn__)) #else - #define NORETURN + #define noreturn #endif #if CLANG_AT_LEAST(3, 6) diff --git a/meson.build b/meson.build index 2d96d62c..f943211c 100644 --- a/meson.build +++ b/meson.build @@ -106,6 +106,7 @@ version = custom_target( misc = static_library( 'misc', + 'debug.c', 'debug.h', 'hsl.c', 'hsl.h', 'log.c', 'log.h', 'macros.h', @@ -180,6 +181,7 @@ executable( executable( 'footclient', 'client.c', 'client-protocol.h', + 'debug.c', 'debug.h', 'foot-features.h', 'log.c', 'log.h', 'macros.h', diff --git a/reaper.c b/reaper.c index 9d98854e..d2b27986 100644 --- a/reaper.c +++ b/reaper.c @@ -5,11 +5,12 @@ #include #include #include +#include #define LOG_MODULE "reaper" #define LOG_ENABLE_DBG 0 #include "log.h" -#include "tllist.h" +#include "debug.h" struct child { pid_t pid; diff --git a/search.c b/search.c index 05b96ed6..7d1ece7b 100644 --- a/search.c +++ b/search.c @@ -593,7 +593,6 @@ execute_binding(struct seat *seat, struct terminal *term, case BIND_ACTION_SEARCH_EDIT_LEFT_WORD: { size_t diff = distance_prev_word(term); term->search.cursor -= diff; - assert(term->search.cursor >= 0); assert(term->search.cursor <= term->search.len); return false; } @@ -606,7 +605,6 @@ execute_binding(struct seat *seat, struct terminal *term, case BIND_ACTION_SEARCH_EDIT_RIGHT_WORD: { size_t diff = distance_next_word(term); term->search.cursor += diff; - assert(term->search.cursor >= 0); assert(term->search.cursor <= term->search.len); return false; } diff --git a/shm.c b/shm.c index 1d08d56c..f5f94b62 100644 --- a/shm.c +++ b/shm.c @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -22,6 +21,7 @@ #define LOG_MODULE "shm" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" #include "macros.h" #include "xmalloc.h" diff --git a/sixel.c b/sixel.c index 96d2aba2..261446f5 100644 --- a/sixel.c +++ b/sixel.c @@ -6,6 +6,7 @@ #define LOG_MODULE "sixel" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" #include "render.h" #include "hsl.h" #include "util.h" diff --git a/slave.c b/slave.c index eaa21060..01c81b28 100644 --- a/slave.c +++ b/slave.c @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -18,6 +17,7 @@ #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" #include "terminal.h" #include "tokenize.h" #include "xmalloc.h" diff --git a/spawn.c b/spawn.c index 6d96cf54..e0d95985 100644 --- a/spawn.c +++ b/spawn.c @@ -2,7 +2,6 @@ #include #include -#include #include #include @@ -11,6 +10,7 @@ #define LOG_MODULE "spawn" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" bool spawn(struct reaper *reaper, const char *cwd, char *const argv[], diff --git a/terminal.c b/terminal.c index 13f7a6f7..0fe55a60 100644 --- a/terminal.c +++ b/terminal.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -22,6 +21,7 @@ #include "async.h" #include "config.h" +#include "debug.h" #include "extract.h" #include "grid.h" #include "ime.h" diff --git a/terminal.h b/terminal.h index 04d2d5b7..6f1ba1c1 100644 --- a/terminal.h +++ b/terminal.h @@ -12,6 +12,7 @@ #include //#include "config.h" +#include "debug.h" #include "fdm.h" #include "macros.h" #include "reaper.h" diff --git a/uri.c b/uri.c index a0e3838a..21eba6fb 100644 --- a/uri.c +++ b/uri.c @@ -4,11 +4,11 @@ #include #include #include -#include #define LOG_MODULE "uri" #define LOG_ENABLE_DBG 0 #include "log.h" +#include "debug.h" #include "xmalloc.h" enum { diff --git a/vt.c b/vt.c index b932c716..ca69b77c 100644 --- a/vt.c +++ b/vt.c @@ -3,13 +3,13 @@ #include #include #include -#include #define LOG_MODULE "vt" #define LOG_ENABLE_DBG 0 #include "log.h" #include "csi.h" #include "dcs.h" +#include "debug.h" #include "grid.h" #include "osc.h" #include "util.h" diff --git a/xmalloc.c b/xmalloc.c index a9a6685c..8fb78f49 100644 --- a/xmalloc.c +++ b/xmalloc.c @@ -1,21 +1,11 @@ -#include #include #include #include #include #include #include -#include #include "xmalloc.h" - -static NORETURN COLD void -fatal_error(const char *msg, int err) -{ - syslog(LOG_ERR, "%s: %s", msg, strerror(err)); - errno = err; - perror(msg); - abort(); -} +#include "debug.h" static void * check_alloc(void *alloc) diff --git a/xsnprintf.c b/xsnprintf.c index e8e8d25d..9e7693b6 100644 --- a/xsnprintf.c +++ b/xsnprintf.c @@ -1,8 +1,8 @@ #include "xsnprintf.h" -#include #include #include +#include "debug.h" size_t xvsnprintf(char *buf, size_t n, const char *format, va_list ap)