Skip to content

Commit

Permalink
Windows doesn't send pty EOF unless wait is called
Browse files Browse the repository at this point in the history
  • Loading branch information
Naatan committed Jun 28, 2024
1 parent ef53e28 commit e176b0b
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 22 deletions.
15 changes: 2 additions & 13 deletions helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"bytes"
"errors"
"os"
"os/exec"
"strings"
"time"
)
Expand All @@ -23,20 +22,10 @@ type cmdExit struct {
Err error
}

// waitForCmdExit turns process.wait() into a channel so that it can be used within a select{} statement
func waitForCmdExit(cmd *exec.Cmd) chan *cmdExit {
exit := make(chan *cmdExit, 1)
go func() {
err := cmd.Wait()
exit <- &cmdExit{ProcessState: cmd.ProcessState, Err: err}
}()
return exit
}

func waitChan[T any](wait func() T) chan T {
done := make(chan T)
done := make(chan T, 1)
go func() {
done <- wait()
wait()
close(done)
}()
return done
Expand Down
20 changes: 14 additions & 6 deletions termtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type TermTest struct {
ptmx pty.Pty
outputProducer *outputProducer
listenError chan error
waitError chan error
opts *Opts
}

Expand Down Expand Up @@ -78,6 +79,7 @@ func New(cmd *exec.Cmd, opts ...SetOpt) (*TermTest, error) {
cmd: cmd,
outputProducer: newOutputProducer(optv),
listenError: make(chan error, 1),
waitError: make(chan error, 1),
opts: optv,
}

Expand Down Expand Up @@ -227,6 +229,7 @@ func (tt *TermTest) start() (rerr error) {
tt.term = vt10x.New(vt10x.WithWriter(ptmx), vt10x.WithSize(tt.opts.Cols, tt.opts.Rows))

// Start listening for output
// We use a waitgroup here to ensure the listener is active before consumers are attached.
wg := &sync.WaitGroup{}
wg.Add(1)
go func() {
Expand All @@ -235,6 +238,16 @@ func (tt *TermTest) start() (rerr error) {
err := tt.outputProducer.Listen(tt.ptmx, tt.term)
tt.listenError <- err
}()

go func() {
// We start waiting right away, because on Windows the PTY isn't closed until the process exits, which in turn
// can't happen unless we've told the pty we're ready for it to close.
// This of course isn't ideal, but until the pty library fixes the cross-platform inconsistencies we have to
// work around these limitations.
defer tt.opts.Logger.Printf("waitIndefinitely finished")
tt.waitError <- tt.waitIndefinitely()
}()

wg.Wait()

return nil
Expand All @@ -247,13 +260,8 @@ func (tt *TermTest) Wait(timeout time.Duration) (rerr error) {
tt.opts.Logger.Println("wait called")
defer tt.opts.Logger.Println("wait closed")

errc := make(chan error, 1)
go func() {
errc <- tt.WaitIndefinitely()
}()

select {
case err := <-errc:
case err := <-tt.waitError:
// WaitIndefinitely already invokes the expect error handler
return err
case <-time.After(timeout):
Expand Down
2 changes: 1 addition & 1 deletion termtest_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ func syscallErrorCode(err error) int {
return -1
}

func (tt *TermTest) WaitIndefinitely() error {
func (tt *TermTest) waitIndefinitely() error {
tt.opts.Logger.Println("WaitIndefinitely called")
defer tt.opts.Logger.Println("WaitIndefinitely closed")

Expand Down
4 changes: 2 additions & 2 deletions termtest_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ func syscallErrorCode(err error) int {
return 0
}

// WaitIndefinitely on Windows has to work around a Windows PTY bug where the PTY will NEVER exit by itself:
// waitIndefinitely on Windows has to work around a Windows PTY bug where the PTY will NEVER exit by itself:
// https://github.com/photostorm/pty/issues/3
// Instead we wait for the process itself to exit, and after a grace period will shut down the pty.
func (tt *TermTest) WaitIndefinitely() error {
func (tt *TermTest) waitIndefinitely() error {
tt.opts.Logger.Println("WaitIndefinitely called")
defer tt.opts.Logger.Println("WaitIndefinitely closed")

Expand Down

0 comments on commit e176b0b

Please sign in to comment.