From db1d45037cf923bf470a8581d5546bef8247c756 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Fri, 25 Aug 2017 15:57:49 +0200 Subject: [PATCH] Handle SIGWINCH --- src/libutil/util.cc | 28 ++++++++++++++++++++++++++++ src/libutil/util.hh | 10 ++++++++++ src/nix/progress-bar.cc | 9 +-------- 3 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/libutil/util.cc b/src/libutil/util.cc index b7b32b3d3..2f410f7e3 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1254,6 +1255,26 @@ void callFailure(const std::function & failure, st } +static Sync> windowSize{{0, 0}}; + + +static void updateWindowSize() +{ + struct winsize ws; + if (ioctl(1, TIOCGWINSZ, &ws) == 0) { + auto windowSize_(windowSize.lock()); + windowSize_->first = ws.ws_row; + windowSize_->second = ws.ws_col; + } +} + + +std::pair getWindowSize() +{ + return *windowSize.lock(); +} + + static Sync>> _interruptCallbacks; static void signalHandlerThread(sigset_t set) @@ -1264,6 +1285,10 @@ static void signalHandlerThread(sigset_t set) if (signal == SIGINT || signal == SIGTERM || signal == SIGHUP) triggerInterrupt(); + + else if (signal == SIGWINCH) { + updateWindowSize(); + } } } @@ -1287,6 +1312,8 @@ static sigset_t savedSignalMask; void startSignalHandlerThread() { + updateWindowSize(); + if (sigprocmask(SIG_BLOCK, nullptr, &savedSignalMask)) throw SysError("quering signal mask"); @@ -1296,6 +1323,7 @@ void startSignalHandlerThread() sigaddset(&set, SIGTERM); sigaddset(&set, SIGHUP); sigaddset(&set, SIGPIPE); + sigaddset(&set, SIGWINCH); if (pthread_sigmask(SIG_BLOCK, &set, nullptr)) throw SysError("blocking signals"); diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 7340ca6c7..30e3c0df1 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -349,6 +349,12 @@ bool hasSuffix(const string & s, const string & suffix); std::string toLower(const std::string & s); +/* Escape a string that contains octal-encoded escape codes such as + used in /etc/fstab and /proc/mounts (e.g. "foo\040bar" decodes to + "foo bar"). */ +string decodeOctalEscaped(const string & s); + + /* Exception handling in destructors: print an error message, then ignore the exception. */ void ignoreException(); @@ -470,4 +476,8 @@ struct MaintainCount }; +/* Return the number of rows and columns of the terminal. */ +std::pair getWindowSize(); + + } diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index cd5a8fca2..2ad099450 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -6,8 +6,6 @@ #include #include -#include - namespace nix { static std::string getS(const std::vector & fields, size_t n) @@ -99,15 +97,10 @@ private: Sync state_; - int width = 0; - public: ProgressBar() { - struct winsize ws; - if (ioctl(1, TIOCGWINSZ, &ws) == 0) - width = ws.ws_col; } ~ProgressBar() @@ -270,7 +263,7 @@ public: } } - writeToStderr("\r" + ansiTruncate(line, width) + "\e[K"); + writeToStderr("\r" + ansiTruncate(line, getWindowSize().second) + "\e[K"); } std::string getStatus(State & state)