commit: 3e3bb8e67abc421824ccbf978aea6a0040e0ca92 Author: Zac Medico <zmedico <AT> gentoo <DOT> org> AuthorDate: Tue Dec 10 21:13:12 2024 +0000 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> CommitDate: Sat Dec 28 02:04:57 2024 +0000 URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=3e3bb8e6
Scheduler: Handle SIGWINCH for JobStatusDisplay Do not use curses in the get_term_size function, since curses caches the terminal width and does not account for resize. Bug: https://bugs.gentoo.org/945382 Signed-off-by: Zac Medico <zmedico <AT> gentoo.org> NEWS | 2 ++ lib/_emerge/JobStatusDisplay.py | 14 +++++++++----- lib/_emerge/Scheduler.py | 11 +++++++++++ lib/portage/output.py | 15 +++++---------- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/NEWS b/NEWS index f79a11c991..c08f368815 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,8 @@ Bug fixes: * Process elog messages for emerge --config (bug #904702). +* Scheduler: Handle SIGWINCH for JobStatusDisplay (bug #945382). + portage-3.0.66.1 (2024-09-18) -------------- diff --git a/lib/_emerge/JobStatusDisplay.py b/lib/_emerge/JobStatusDisplay.py index 57495c5ae5..b98d4a8327 100644 --- a/lib/_emerge/JobStatusDisplay.py +++ b/lib/_emerge/JobStatusDisplay.py @@ -65,11 +65,9 @@ class JobStatusDisplay: if not isinstance(v, str): self._term_codes[k] = v.decode(encoding, "replace") - if self._isatty: - width = portage.output.get_term_size()[1] - else: - width = self.max_display_width - self._set_width(width) + if not self._isatty: + self._set_width(self.max_display_width) + self.sigwinch() def _set_width(self, width): if width == getattr(self, "width", None): @@ -79,6 +77,12 @@ class JobStatusDisplay: object.__setattr__(self, "width", width) object.__setattr__(self, "_jobs_column_width", width - 32) + def sigwinch(self): + if not self._isatty: + return + width = portage.output.get_term_size()[1] + self._set_width(width) + @property def out(self): """Use a lazy reference to sys.stdout, in case the API consumer has diff --git a/lib/_emerge/Scheduler.py b/lib/_emerge/Scheduler.py index fea151d5d1..96843c96ee 100644 --- a/lib/_emerge/Scheduler.py +++ b/lib/_emerge/Scheduler.py @@ -1177,6 +1177,9 @@ class Scheduler(PollScheduler): ) signal.siginterrupt(signal.SIGCONT, False) + earlier_sigwinch_handler = signal.signal( + signal.SIGWINCH, self._sigwinch_handler + ) try: rval = self._merge() finally: @@ -1194,6 +1197,11 @@ class Scheduler(PollScheduler): else: signal.signal(signal.SIGCONT, signal.SIG_DFL) + if earlier_sigwinch_handler is not None: + signal.signal(signal.SIGWINCH, earlier_sigwinch_handler) + else: + signal.signal(signal.SIGWINCH, signal.SIG_DFL) + self._termination_check() if received_signal: sys.exit(received_signal[0]) @@ -1909,6 +1917,9 @@ class Scheduler(PollScheduler): def _sigcont_handler(self, signum, frame): self._sigcont_time = time.time() + def _sigwinch_handler(self, signum, frame): + self._status_display.sigwinch() + def _job_delay(self): """ @rtype: bool diff --git a/lib/portage/output.py b/lib/portage/output.py index 4408705c45..9c78a4c298 100644 --- a/lib/portage/output.py +++ b/lib/portage/output.py @@ -522,16 +522,11 @@ def get_term_size(fd=None): fd = sys.stdout if not hasattr(fd, "isatty") or not fd.isatty(): return (0, 0) - try: - import curses - - try: - curses.setupterm(term=os.environ.get("TERM", "unknown"), fd=fd.fileno()) - return curses.tigetnum("lines"), curses.tigetnum("cols") - except curses.error: - pass - except ImportError: - pass + + # Do not use curses.tigetnum("lines") or curses.tigetnum("cols") because it + # returns stale values after terminal resize. Do not use curses.initscr().getmaxyx() + # since that has unwanted side-effects, requiring a call to `stty sane` to restore a + # sane state. try: proc = subprocess.Popen(["stty", "size"], stdout=subprocess.PIPE, stderr=fd)
