From 7b1fa1bf49c2573ae640927cde3362e735ea0b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= Date: Fri, 25 Dec 2020 11:03:15 +0100 Subject: [PATCH] Cache stderr to be able to print assert messages --- CRT.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 1 + 2 files changed, 94 insertions(+) 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 #endif +#if !defined(NDEBUG) && defined(HAVE_MEMFD_CREATE) +#include +#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) { diff --git a/configure.ac b/configure.ac index 7bac0426..4626b592 100644 --- a/configure.ac +++ b/configure.ac @@ -189,6 +189,7 @@ AC_CHECK_FUNCS([ \ faccessat \ fstatat \ host_get_clock_service \ + memfd_create\ openat \ readlinkat \ ])