Skip to content

Commit

Permalink
fix: windows: handle cancel io error
Browse files Browse the repository at this point in the history
This gracefully handles windows.CancelIo errors.

Fixes: c8d6005 (fix: use CancelIoEx to cancel Windows conInputReader across threads (#1305))
Fixes: #1324
  • Loading branch information
aymanbagabas committed Feb 10, 2025
1 parent 771a101 commit b0186ad
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 6 deletions.
14 changes: 12 additions & 2 deletions inputreader_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ func (r *conInputReader) Close() error {
}

// Read implements cancelreader.CancelReader.
func (*conInputReader) Read(_ []byte) (n int, err error) {
return 0, nil
func (r *conInputReader) Read(_ []byte) (n int, err error) {
if r.isCanceled() {
err = cancelreader.ErrCanceled
}
return
}

func prepareConsole(input windows.Handle, modes ...uint32) (originalMode uint32, err error) {
Expand Down Expand Up @@ -105,3 +108,10 @@ func (c *cancelMixin) setCanceled() {

c.unsafeCanceled = true
}

func (c *cancelMixin) isCanceled() bool {
c.lock.Lock()
defer c.lock.Unlock()

return c.unsafeCanceled
}
11 changes: 7 additions & 4 deletions key_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,26 @@ import (

"github.com/erikgeiser/coninput"
localereader "github.com/mattn/go-localereader"
"golang.org/x/sys/windows"
"github.com/muesli/cancelreader"
)

func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error {
if coninReader, ok := input.(*conInputReader); ok {
return readConInputs(ctx, msgs, coninReader.conin)
return readConInputs(ctx, msgs, coninReader)
}

return readAnsiInputs(ctx, msgs, localereader.NewReader(input))
}

func readConInputs(ctx context.Context, msgsch chan<- Msg, con windows.Handle) error {
func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInputReader) error {
var ps coninput.ButtonState // keep track of previous mouse state
var ws coninput.WindowBufferSizeEventRecord // keep track of the last window size event
for {
events, err := coninput.ReadNConsoleInputs(con, 16)
events, err := coninput.ReadNConsoleInputs(con.conin, 16)

Check failure on line 28 in key_windows.go

View workflow job for this annotation

GitHub Actions / lint / lint-soft (windows-latest)

Magic number: 16, in <argument> detected (mnd)

Check failure on line 28 in key_windows.go

View workflow job for this annotation

GitHub Actions / lint / lint-soft (windows-latest)

Magic number: 16, in <argument> detected (mnd)
if err != nil {
if con.isCanceled() {
return cancelreader.ErrCanceled
}
return fmt.Errorf("read coninput events: %w", err)
}

Expand Down

0 comments on commit b0186ad

Please sign in to comment.