summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2024-04-06 19:41:17 +0200
committerChristian Göttsche <cgzones@googlemail.com>2024-04-13 21:46:04 +0200
commit2fafa349a7d133b7237e0f4f94873a5941435b98 (patch)
tree21f4244a8fa425212e724dcf36d4975dbe503b17
parent49bad52fc2f7f4ebae5ebf33d96e0f01d69ee905 (diff)
Avoid fprintf in signal handlers
fprintf(3) is not safe to call ins signal handlers due to file buffering and memory allocations. Format messages in signal handlers via snprintf(3) and output them via write(2).
-rw-r--r--CRT.c48
-rw-r--r--XUtils.h4
2 files changed, 34 insertions, 18 deletions
diff --git a/CRT.c b/CRT.c
index 3c6c8c49..149cd519 100644
--- a/CRT.c
+++ b/CRT.c
@@ -843,9 +843,11 @@ static void CRT_handleSIGTERM(int sgn) {
if (!signal_str)
signal_str = "unknown reason";
- fprintf(stderr,
+ char err_buf[512];
+ snprintf(err_buf, sizeof(err_buf),
"A signal %d (%s) was received, exiting without persisting settings to htoprc.\n",
sgn, signal_str);
+ full_write_str(STDERR_FILENO, err_buf);
_exit(0);
}
@@ -912,7 +914,7 @@ static void dumpStderr(void) {
if (res > 0) {
if (!header) {
- fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n");
+ full_write_str(STDERR_FILENO, ">>>>>>>>>> stderr output >>>>>>>>>>\n");
header = true;
}
full_write(STDERR_FILENO, buffer, res);
@@ -920,7 +922,7 @@ static void dumpStderr(void) {
}
if (header)
- fprintf(stderr, "\n<<<<<<<<<< stderr output <<<<<<<<<<\n");
+ full_write_str(STDERR_FILENO, "\n<<<<<<<<<< stderr output <<<<<<<<<<\n");
close(stderrRedirectNewFd);
stderrRedirectNewFd = -1;
@@ -1185,6 +1187,8 @@ static void print_backtrace(void) {
unsigned int item = 0;
+ char err_buf[1024];
+
while (unw_step(&cursor) > 0) {
unw_word_t pc;
unw_get_reg(&cursor, UNW_REG_IP, &pc);
@@ -1213,7 +1217,8 @@ static void print_backtrace(void) {
const bool is_signal_frame = unw_is_signal_frame(&cursor) > 0;
const char* frame = is_signal_frame ? " {signal frame}" : "";
- fprintf(stderr, "%2u: %#14lx %s (%s+%#lx) [%p]%s\n", item++, pc, fname, symbolName, offset, ptr, frame);
+ snprintf(err_buf, sizeof(err_buf), "%2u: %#14lx %s (%s+%#lx) [%p]%s\n", item++, pc, fname, symbolName, offset, ptr, frame);
+ full_write_str(STDERR_FILENO, err_buf);
}
#elif defined(HAVE_EXECINFO_H)
void* backtraceArray[256];
@@ -1229,7 +1234,9 @@ static void print_backtrace(void) {
void CRT_handleSIGSEGV(int signal) {
CRT_done();
- fprintf(stderr, "\n\n"
+ char err_buf[512];
+
+ snprintf(err_buf, sizeof(err_buf), "\n\n"
"FATAL PROGRAM ERROR DETECTED\n"
"============================\n"
"Please check at https://htop.dev/issues whether this issue has already been reported.\n"
@@ -1240,12 +1247,13 @@ void CRT_handleSIGSEGV(int signal) {
" - Likely steps to reproduce (How did it happen?)\n",
program
);
+ full_write_str(STDERR_FILENO, err_buf);
#ifdef PRINT_BACKTRACE
- fprintf(stderr, " - Backtrace of the issue (see below)\n");
+ full_write_str(STDERR_FILENO, " - Backtrace of the issue (see below)\n");
#endif
- fprintf(stderr,
+ full_write_str(STDERR_FILENO,
"\n"
);
@@ -1253,29 +1261,30 @@ void CRT_handleSIGSEGV(int signal) {
if (!signal_str) {
signal_str = "unknown reason";
}
- fprintf(stderr,
+ snprintf(err_buf, sizeof(err_buf),
"Error information:\n"
"------------------\n"
"A signal %d (%s) was received.\n"
"\n",
signal, signal_str
);
+ full_write_str(STDERR_FILENO, err_buf);
- fprintf(stderr,
+ full_write_str(STDERR_FILENO,
"Setting information:\n"
"--------------------\n");
Settings_write(CRT_crashSettings, true);
- fprintf(stderr, "\n\n");
+ full_write_str(STDERR_FILENO, "\n\n");
#ifdef PRINT_BACKTRACE
- fprintf(stderr,
+ full_write_str(STDERR_FILENO,
"Backtrace information:\n"
"----------------------\n"
);
print_backtrace();
- fprintf(stderr,
+ snprintf(err_buf, sizeof(err_buf),
"\n"
"To make the above information more practical to work with, "
"please also provide a disassembly of your %s binary. "
@@ -1283,31 +1292,34 @@ void CRT_handleSIGSEGV(int signal) {
"\n",
program
);
+ full_write_str(STDERR_FILENO, err_buf);
#ifdef HTOP_DARWIN
- fprintf(stderr, " otool -tvV `which %s` > ~/%s.otool\n", program, program);
+ snprintf(err_buf, sizeof(err_buf), " otool -tvV `which %s` > ~/%s.otool\n", program, program);
#else
- fprintf(stderr, " objdump -d -S -w `which %s` > ~/%s.objdump\n", program, program);
+ snprintf(err_buf, sizeof(err_buf), " objdump -d -S -w `which %s` > ~/%s.objdump\n", program, program);
#endif
+ full_write_str(STDERR_FILENO, err_buf);
- fprintf(stderr,
+ full_write_str(STDERR_FILENO,
"\n"
"Please include the generated file in your report.\n"
);
#endif
- fprintf(stderr,
+ snprintf(err_buf, sizeof(err_buf),
"Running this program with debug symbols or inside a debugger may provide further insights.\n"
"\n"
"Thank you for helping to improve %s!\n"
"\n",
program
);
+ full_write_str(STDERR_FILENO, err_buf);
/* Call old sigsegv handler; may be default exit or third party one (e.g. ASAN) */
if (sigaction(signal, &old_sig_handler[signal], NULL) < 0) {
/* This avoids an infinite loop in case the handler could not be reset. */
- fprintf(stderr,
+ full_write_str(STDERR_FILENO,
"!!! Chained handler could not be restored. Forcing exit.\n"
);
_exit(1);
@@ -1317,7 +1329,7 @@ void CRT_handleSIGSEGV(int signal) {
raise(signal);
// Always terminate, even if installed handler returns
- fprintf(stderr,
+ full_write_str(STDERR_FILENO,
"!!! Chained handler did not exit. Forcing exit.\n"
);
_exit(1);
diff --git a/XUtils.h b/XUtils.h
index 32bc282d..3703f8bc 100644
--- a/XUtils.h
+++ b/XUtils.h
@@ -117,6 +117,10 @@ ssize_t xReadfileat(openat_arg_t dirfd, const char* pathname, void* buffer, size
ATTR_ACCESS3_R(2, 3)
ssize_t full_write(int fd, const void* buf, size_t count);
+static inline ssize_t full_write_str(int fd, const char* str) {
+ return full_write(fd, str, strlen(str));
+}
+
/* Compares floating point values for ordering data entries. In this function,
NaN is considered "less than" any other floating point value (regardless of
sign), and two NaNs are considered "equal" regardless of payload. */

© 2014-2024 Faster IT GmbH | imprint | privacy policy