Documentation
¶
Overview ¶
Package ptyproc owns the process and PTY lifecycle for tuitest: spawning a child attached to a pseudo-terminal, pumping its output, resizing, EOF and exit-code handling, and process-tree teardown. It is deliberately separate from the screen-matching logic so the two compose independently (the go-expect separation of console ownership from expectation matching).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Probe ¶
Probe reports whether a pseudo-terminal can be allocated at all, by opening one and immediately closing it. It spawns no child, so it is safe to call from diagnostics without risking a stray process. A non-nil error is the reason allocation failed, which on a container without /dev/pts is exactly what a user needs to see.
Types ¶
type Config ¶
type Config struct {
Argv []string // argv[0] is the program, argv[1:] the arguments
Env []string // full environment ("KEY=VALUE" entries)
Dir string // working directory, empty for inherit
Cols int
Rows int
}
Config configures a spawn.
type Handler ¶
type Handler struct {
// OnData is called with each chunk read from the PTY master. The slice is
// owned by the callback for the duration of the call only.
OnData func([]byte)
// OnClose is called once, after the child has exited and been reaped, with
// its exit code (-1 if unknown).
OnClose func(code int)
}
Handler receives lifecycle callbacks from the pump goroutine. Callbacks are invoked from a single dedicated goroutine, never concurrently with each other, so the receiver only needs to guard state it also touches elsewhere.
type Process ¶
type Process struct {
// contains filtered or unexported fields
}
Process is a spawned child attached to a PTY.
func (*Process) Close ¶
Close tears down the whole process tree and closes the PTY. It is idempotent and safe to call from a cleanup hook even after the child exited.
It returns a non-nil error when something the child spawned was still running after SIGKILL, or failing that when the PTY could not be released. Both are leaks the caller needs to know about, the process one most of all: a test that ignores it hands the next test a machine with stray processes on it, which is how a suite ends up flooding a workstation.
func (*Process) Done ¶
func (p *Process) Done() <-chan struct{}
Done returns a channel closed once the child has been reaped and the Handler's OnClose callback has returned.
func (*Process) ExitCode ¶
ExitCode reports the child's exit code and whether it has exited.
The code is -1 for a child that died from a signal, which is what os.ProcessState.ExitCode reports and not the shell's 128+signal convention: a harness that invented 137 for SIGKILL would be unable to tell it apart from a program that genuinely exited 137. It is also -1 before the child has exited at all, so the second return value is the only thing that separates the two, and ExitStatus is what distinguishes a crash from an ordinary failure.
func (*Process) ExitStatus ¶
ExitStatus reports how the child finished, including signal death, and whether it has exited at all.
func (*Process) Resize ¶
Resize changes the PTY window size; the kernel delivers SIGWINCH to the child.
func (*Process) Write ¶
Write sends input bytes to the child. Write sends bytes to the child. Two goroutines write here: the caller sending keystrokes, and the output pump forwarding emulator query responses. The lock keeps a short write from being interleaved into the middle of an escape sequence from the other writer.