Skip to content

Instantly share code, notes, and snippets.

@dsanson
Created May 25, 2020 21:16
Show Gist options
  • Save dsanson/35f54a4b621c849693e3166d2ba49325 to your computer and use it in GitHub Desktop.
Save dsanson/35f54a4b621c849693e3166d2ba49325 to your computer and use it in GitHub Desktop.
Patch to fix bug in fish that causes incorrect terminal size reporting
https://github.com/fish-shell/fish-shell/issues/6994#issuecomment-633303722
diff --git a/src/common.cpp b/src/common.cpp
index f76445fc0..57d66695a 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -103,7 +103,7 @@ static relaxed_atomic_t<pid_t> initial_fg_process_group{-1};
/// This struct maintains the current state of the terminal size. It is updated on demand after
/// receiving a SIGWINCH. Use common_get_width()/common_get_height() to read it lazily.
static constexpr struct winsize k_invalid_termsize = {USHRT_MAX, USHRT_MAX, USHRT_MAX, USHRT_MAX};
-static owning_lock<struct winsize> s_termsize{k_invalid_termsize};
+static relaxed_atomic_t<struct winsize> s_termsize(k_invalid_termsize);
static relaxed_atomic_bool_t s_termsize_valid{false};
@@ -1749,8 +1749,9 @@ bool unescape_string(const wcstring &input, wcstring *output, unescape_flags_t e
void invalidate_termsize(bool invalidate_vars) {
s_termsize_valid = false;
if (invalidate_vars) {
- auto termsize = s_termsize.acquire();
- termsize->ws_col = termsize->ws_row = USHRT_MAX;
+ struct winsize termsize = s_termsize;
+ termsize.ws_col = termsize.ws_row = USHRT_MAX;
+ termsize = s_termsize;
}
}
@@ -1818,42 +1819,27 @@ static void export_new_termsize(struct winsize *new_termsize, env_stack_t &vars)
#endif
}
-/// Get the current termsize, lazily computing it. Return by reference if it changed.
-static struct winsize get_current_winsize_prim(bool *changed, const environment_t &vars) {
- auto termsize = s_termsize.acquire();
- if (s_termsize_valid) return *termsize;
+/// Updates termsize as needed, and returns a copy of the winsize.
+struct winsize get_current_winsize() {
+ struct winsize termsize = s_termsize;
+ if (s_termsize_valid) return termsize;
struct winsize new_termsize = {0, 0, 0, 0};
#ifdef HAVE_WINSIZE
errno = 0;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &new_termsize) != -1 &&
- new_termsize.ws_col == termsize->ws_col && new_termsize.ws_row == termsize->ws_row) {
+ new_termsize.ws_col == termsize.ws_col && new_termsize.ws_row == termsize.ws_row) {
s_termsize_valid = true;
- return *termsize;
+ return termsize;
}
#endif
+ auto &vars = env_stack_t::globals();
validate_new_termsize(&new_termsize, vars);
- termsize->ws_col = new_termsize.ws_col;
- termsize->ws_row = new_termsize.ws_row;
- *changed = true;
+ export_new_termsize(&new_termsize, vars);
+ termsize.ws_col = new_termsize.ws_col;
+ termsize.ws_row = new_termsize.ws_row;
+ s_termsize = termsize;
s_termsize_valid = true;
- return *termsize;
-}
-
-/// Updates termsize as needed, and returns a copy of the winsize.
-struct winsize get_current_winsize() {
- bool changed = false;
- auto &vars = env_stack_t::globals();
- struct winsize termsize = get_current_winsize_prim(&changed, vars);
- if (changed) {
- // TODO: this may call us reentrantly through the environment dispatch mechanism. We need to
- // rationalize this.
- export_new_termsize(&termsize, vars);
- // Hack: due to the dispatch the termsize may have just become invalid. Stomp it back to
- // valid. What a mess.
- *s_termsize.acquire() = termsize;
- s_termsize_valid = true;
- }
return termsize;
}
diff --git a/src/common.h b/src/common.h
index d453e4b1d..a83a3de15 100644
--- a/src/common.h
+++ b/src/common.h
@@ -494,7 +494,6 @@ class owning_lock {
public:
owning_lock(Data &&d) : data(std::move(d)) {}
- owning_lock(const Data &d) : data(d) {}
owning_lock() : data() {}
acquired_lock<Data> acquire() { return {lock, &data}; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment