cancelreader

package
v0.0.0-...-64e189b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 3, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package cancelreader is an io.Reader over an *os.File whose blocked Read can be cancelled from another goroutine.

Program needs this to stop its input reader when Run returns. The obvious tool, File.SetReadDeadline, does not work for a terminal: os.Stdin is a blocking descriptor Go never registers with its poller (so there is no deadline support at all), and calling File.Fd() — which Run does — switches even a pollable file to blocking mode, after which SetReadDeadline returns nil yet no longer interrupts a Read. The stranded reader then outlives Run and steals keys from whatever reads the terminal next.

On darwin and linux the Reader waits with select(2) on the file and on an internal cancel pipe, and only reads once the file is readable, so Cancel never leaves a Read half-done and never consumes input. On windows it polls the handle (PeekNamedPipe for pipes, WaitForSingleObject for a console) and reads only once input is there, so a Cancel lands within a short slice. On other platforms it falls back to the read-deadline behaviour Program used before, which is best effort and unverified there.

The file must stay open until the Reader is closed: the Reader waits on the raw descriptor, and closing a descriptor under a waiting select is undefined (and its number can be reused).

Index

Constants

This section is empty.

Variables

View Source
var ErrCanceled = errors.New("cancelreader: read canceled")

ErrCanceled is returned by Read after Cancel.

Functions

This section is empty.

Types

type Reader

type Reader struct {
	// contains filtered or unexported fields
}

Reader reads from a file and can be cancelled. Read is meant to be called from one goroutine; Cancel may be called from any goroutine, any number of times. Close releases the cancel pipe and must only be called once Read has returned (the reading goroutine defers it).

func New

func New(f *os.File) (*Reader, error)

New returns a Reader for f. It does not take ownership of f, change its blocking mode, or close it.

func (*Reader) Cancel

func (r *Reader) Cancel()

Cancel makes a waiting Read, and every later one, return ErrCanceled.

func (*Reader) Close

func (r *Reader) Close()

Close releases the cancel pipe. It is safe to call more than once.

func (*Reader) Read

func (r *Reader) Read(p []byte) (int, error)

Read waits until the file is readable or the Reader is cancelled. After a cancel it returns ErrCanceled without reading, so pending input stays in the file for the next reader.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL