From 39c2d084c76f5c3c64e73ecd81bc6b51b5711b45 Mon Sep 17 00:00:00 2001 From: Dylan Corrales Date: Sun, 8 Nov 2026 11:16:18 -0500 Subject: [PATCH] Keeping errno for HAL messages logged to a file or pipe The HAL_* macros pick their colours with isatty(STDERR_FILENO) before a message's arguments are evaluated. When stderr is not a terminal (a log file, a pipe, a service manager), isatty() sets errno to ENOTTY, so every message that reports strerror(errno) printed "Not a tty" (musl) or "Inappropriate ioctl for device" (glibc) instead of the failure it was about. The colour test now keeps errno. Found while running the Ambarella S3L backend (#71) with its log redirected: a refused ioctl that returned EPERM was reported as "Not a tty". Tested with a HAL_DANGER(..., strerror(errno)) after errno = EPERM: stderr to a file printed "Inappropriate ioctl for device" before and "Operation not permitted" after; on a terminal both print the latter. --- src/hal/macros.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/hal/macros.h b/src/hal/macros.h index 47492da3..615afd0c 100644 --- a/src/hal/macros.h +++ b/src/hal/macros.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -26,7 +27,15 @@ ".balign 4\n" /* Word alignment */\ ".section \".text\"\n") /* Restore section */ -#define HAL_COLOR(seq) (isatty(STDERR_FILENO) ? (seq) : "") +/* isatty() sets errno (ENOTTY) when stderr is not a terminal, and the colour test runs before a message's + arguments are evaluated: keep errno, or every strerror(errno) logged to a file or pipe reads "Not a tty" */ +static inline int hal_stderr_is_tty(void) { + int err = errno, tty = isatty(STDERR_FILENO); + errno = err; + return tty; +} + +#define HAL_COLOR(seq) (hal_stderr_is_tty() ? (seq) : "") #define HAL_DANGER(mod, x, ...) \ do { \