summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2025-02-04 13:45:45 -0500
committerTavian Barnes <tavianator@tavianator.com>2025-02-06 10:38:44 -0500
commitf8aca1c316b116c2de11d42010fdda0ddb418750 (patch)
treec75e31e1f895c92721fa31be2c559335b21de714
parent532dec0849dcdc3e15e530ac40a8168f146a41cd (diff)
downloadbfs-f8aca1c316b116c2de11d42010fdda0ddb418750.tar.xz
diag: Try to make diagnostics signal-safer
Link: https://sourceware.org/bugzilla/show_bug.cgi?id=16060
-rw-r--r--build/has/dprintf.c8
-rw-r--r--build/header.mk1
-rw-r--r--src/diag.c19
3 files changed, 25 insertions, 3 deletions
diff --git a/build/has/dprintf.c b/build/has/dprintf.c
new file mode 100644
index 0000000..c206fa3
--- /dev/null
+++ b/build/has/dprintf.c
@@ -0,0 +1,8 @@
+// Copyright © Tavian Barnes <tavianator@tavianator.com>
+// SPDX-License-Identifier: 0BSD
+
+#include <stdio.h>
+
+int main(void) {
+ return dprintf(1, "%s\n", "Hello world!");
+}
diff --git a/build/header.mk b/build/header.mk
index 6a63221..f8aee4b 100644
--- a/build/header.mk
+++ b/build/header.mk
@@ -21,6 +21,7 @@ HEADERS := \
gen/has/builtin-riscv-pause.h \
gen/has/compound-literal-storage.h \
gen/has/confstr.h \
+ gen/has/dprintf.h \
gen/has/extattr-get-file.h \
gen/has/extattr-get-link.h \
gen/has/extattr-list-file.h \
diff --git a/src/diag.c b/src/diag.c
index 4909cf5..4f1c84c 100644
--- a/src/diag.c
+++ b/src/diag.c
@@ -14,13 +14,26 @@
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+
+/**
+ * Print an error using dprintf() if possible, because it's more likely to be
+ * async-signal-safe in practice.
+ */
+#if BFS_HAS_DPRINTF
+# define eprintf(...) dprintf(STDERR_FILENO, __VA_ARGS__)
+# define veprintf(...) vdprintf(STDERR_FILENO, __VA_ARGS__)
+#else
+# define eprintf(...) fprintf(stderr, __VA_ARGS__)
+# define veprintf(...) vfprintf(stderr, __VA_ARGS__)
+#endif
/** bfs_diagf() implementation. */
_printf(2, 0)
static void bfs_vdiagf(const struct bfs_loc *loc, const char *format, va_list args) {
- fprintf(stderr, "%s: %s@%s:%d: ", xgetprogname(), loc->func, loc->file, loc->line);
- vfprintf(stderr, format, args);
- fprintf(stderr, "\n");
+ eprintf("%s: %s@%s:%d: ", xgetprogname(), loc->func, loc->file, loc->line);
+ veprintf(format, args);
+ eprintf("\n");
}
void bfs_diagf(const struct bfs_loc *loc, const char *format, ...) {