From dc384afb7035e86baeb1da85eced7a9b8d4f3c54 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Mon, 20 Jul 2026 13:09:06 +0900 Subject: [PATCH] Terminate resize notification when Loop exits - Pass Loop context to notifyOnResize - Windows: stop polling goroutine, close CONOUT$ handle on ctx.Done - Unix: unregister SIGWINCH handler on ctx.Done --- src/terminal.go | 2 +- src/terminal_unix.go | 7 ++++++- src/terminal_windows.go | 13 +++++++++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/terminal.go b/src/terminal.go index 2d42bb9b..02563bc5 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -6199,7 +6199,7 @@ func (t *Terminal) Loop() error { if !t.tui.ShouldEmitResizeEvent() { resizeChan := make(chan os.Signal, 1) - notifyOnResize(resizeChan) // Non-portable + notifyOnResize(ctx, resizeChan) // Non-portable go func() { for { select { diff --git a/src/terminal_unix.go b/src/terminal_unix.go index 7afa2220..0fedb448 100644 --- a/src/terminal_unix.go +++ b/src/terminal_unix.go @@ -3,6 +3,7 @@ package fzf import ( + "context" "os" "os/signal" "syscall" @@ -10,8 +11,12 @@ import ( "golang.org/x/sys/unix" ) -func notifyOnResize(resizeChan chan<- os.Signal) { +func notifyOnResize(ctx context.Context, resizeChan chan<- os.Signal) { signal.Notify(resizeChan, syscall.SIGWINCH) + go func() { + <-ctx.Done() + signal.Stop(resizeChan) + }() } func notifyStop(p *os.Process) { diff --git a/src/terminal_windows.go b/src/terminal_windows.go index 1325a49f..8d767edd 100644 --- a/src/terminal_windows.go +++ b/src/terminal_windows.go @@ -3,6 +3,7 @@ package fzf import ( + "context" "os" "syscall" "time" @@ -19,19 +20,27 @@ func (resizeSignal) Signal() {} // Windows has no SIGWINCH, so poll the console screen buffer for window // size changes instead. -func notifyOnResize(resizeChan chan<- os.Signal) { +func notifyOnResize(ctx context.Context, resizeChan chan<- os.Signal) { consoleOut, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0) if err != nil { return } var info windows.ConsoleScreenBufferInfo if windows.GetConsoleScreenBufferInfo(windows.Handle(consoleOut), &info) != nil { + syscall.Close(consoleOut) return } last := info.Window go func() { + defer syscall.Close(consoleOut) + ticker := time.NewTicker(resizePollInterval) + defer ticker.Stop() for { - time.Sleep(resizePollInterval) + select { + case <-ctx.Done(): + return + case <-ticker.C: + } if windows.GetConsoleScreenBufferInfo(windows.Handle(consoleOut), &info) != nil { continue }