summaryrefslogtreecommitdiffstats
path: root/CRT.c
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2020-12-25 11:03:15 +0100
committerChristian Göttsche <cgzones@googlemail.com>2021-02-05 19:21:28 +0100
commit7b1fa1bf49c2573ae640927cde3362e735ea0b3a (patch)
treeb6e963a5739597ff7692649f647d0ea00961787f /CRT.c
parent64a1ab848f4cba7b9dd4705a169034e39048d27d (diff)
Cache stderr to be able to print assert messages
Diffstat (limited to 'CRT.c')
-rw-r--r--CRT.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/CRT.c b/CRT.c
index 93a983c4..7e651c3b 100644
--- a/CRT.c
+++ b/CRT.c
@@ -24,6 +24,10 @@ in the source distribution for its full text.
#include <execinfo.h>
#endif
+#if !defined(NDEBUG) && defined(HAVE_MEMFD_CREATE)
+#include <sys/mman.h>
+#endif
+
#define ColorIndex(i,j) ((7-(i))*8+(j))
@@ -685,9 +689,96 @@ void CRT_restorePrivileges() {
#endif /* HAVE_SETUID_ENABLED */
+#ifndef NDEBUG
+
+static int stderrRedirectNewFd = -1;
+static int stderrRedirectBackupFd = -1;
+
+static int createStderrCacheFile(void) {
+#ifdef HAVE_MEMFD_CREATE
+ return memfd_create("htop.stderr-redirect", 0);
+#elif defined(O_TMPFILE)
+ return open("/tmp", O_TMPFILE | O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
+#else
+ char tmpName[] = "htop.stderr-redirectXXXXXX";
+ mode_t curUmask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
+ int r = mkstemp(tmpName);
+ umask(curUmask);
+ if (r < 0)
+ return r;
+
+ (void) unlink(tmpName);
+
+ return r;
+#endif /* HAVE_MEMFD_CREATE */
+}
+
+static void redirectStderr(void) {
+ stderrRedirectNewFd = createStderrCacheFile();
+ if (stderrRedirectNewFd < 0) {
+ /* ignore failure */
+ return;
+ }
+
+ stderrRedirectBackupFd = dup(STDERR_FILENO);
+ dup2(stderrRedirectNewFd, STDERR_FILENO);
+}
+
+static void dumpStderr(void) {
+ if (stderrRedirectNewFd < 0)
+ return;
+
+ fsync(STDERR_FILENO);
+ dup2(stderrRedirectBackupFd, STDERR_FILENO);
+ lseek(stderrRedirectNewFd, 0, SEEK_SET);
+
+ bool header = false;
+ char buffer[8192];
+ for (;;) {
+ errno = 0;
+ ssize_t res = read(stderrRedirectNewFd, buffer, sizeof(buffer));
+ if (res < 0) {
+ if (errno == EINTR)
+ continue;
+
+ break;
+ }
+
+ if (res == 0) {
+ break;
+ }
+
+ if (res > 0) {
+ if (!header) {
+ fprintf(stderr, ">>>>>>>>>> stderr output >>>>>>>>>>\n\n");
+ header = true;
+ }
+ (void)! write(STDERR_FILENO, buffer, res);
+ }
+ }
+
+ if (header)
+ fprintf(stderr, "\n<<<<<<<<<< stderr output <<<<<<<<<<\n");
+
+ close(stderrRedirectNewFd);
+ stderrRedirectNewFd = -1;
+}
+
+#else /* !NDEBUG */
+
+static void redirectStderr(void) {
+}
+
+static void dumpStderr(void) {
+}
+
+#endif /* !NDEBUG */
+
static struct sigaction old_sig_handler[32];
void CRT_init(const Settings* settings, bool allowUnicode) {
+ redirectStderr();
+
initscr();
noecho();
CRT_delay = &(settings->delay);
@@ -788,6 +879,8 @@ void CRT_init(const Settings* settings, bool allowUnicode) {
void CRT_done() {
curs_set(1);
endwin();
+
+ dumpStderr();
}
void CRT_fatalError(const char* note) {

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