From b5d904cb14da0b3a00c157bdb0cec41d29cffa68 Mon Sep 17 00:00:00 2001 From: Will Owens Date: Sun, 26 Oct 2025 13:17:02 -0500 Subject: [PATCH] webtty: upgrade Run to use an errgroup to join 2 i/o routines --- go.mod | 3 +- go.sum | 2 ++ server/handlers.go | 5 ++- webtty/webtty.go | 83 ++++++++++++++++++++++++---------------------- 4 files changed, 52 insertions(+), 41 deletions(-) diff --git a/go.mod b/go.mod index 13624fc..03cd5c2 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/ghthor/gotty/v2 -go 1.23.0 +go 1.24.0 require ( github.com/NYTimes/gziphandler v1.1.1 @@ -11,6 +11,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/urfave/cli v1.22.14 github.com/yudai/hcl v0.0.0-20151013225006-5fa2393b3552 + golang.org/x/sync v0.17.0 ) require ( diff --git a/go.sum b/go.sum index 2ce9786..50ae37f 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,8 @@ github.com/yudai/hcl v0.0.0-20151013225006-5fa2393b3552 h1:tjsK9T2IA3d2FFNxzDP7A github.com/yudai/hcl v0.0.0-20151013225006-5fa2393b3552/go.mod h1:hg0ZaCmQL3rze1cH8Fh2g0a9q8vQs0uN8ESpePEwSEw= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/server/handlers.go b/server/handlers.go index ae51424..4f3f8fc 100644 --- a/server/handlers.go +++ b/server/handlers.go @@ -165,8 +165,11 @@ func (server *Server) processWSConn(ctx context.Context, conn *websocket.Conn) e } err = tty.Run(ctx) + if err != nil && !errors.Is(err, context.Canceled) { + return err + } - return err + return nil } func (server *Server) handleIndex(w http.ResponseWriter, r *http.Request) { diff --git a/webtty/webtty.go b/webtty/webtty.go index ed4f8b9..9036e8d 100644 --- a/webtty/webtty.go +++ b/webtty/webtty.go @@ -7,6 +7,7 @@ import ( "sync" "github.com/pkg/errors" + "golang.org/x/sync/errgroup" ) // WebTTY bridges a PTY slave and its PTY master. @@ -42,7 +43,7 @@ func New(masterConn Master, slave Slave, options ...Option) (*WebTTY, error) { columns: 0, rows: 0, - bufferSize: 1024, + bufferSize: 4096, } for _, option := range options { @@ -64,49 +65,52 @@ func (wt *WebTTY) Run(ctx context.Context) error { return errors.Wrapf(err, "failed to send initializing message") } - errs := make(chan error, 2) + grp, grpCtx := errgroup.WithContext(ctx) + done := grpCtx.Done() - go func() { - errs <- func() error { - buffer := make([]byte, wt.bufferSize) - for { - n, err := wt.slave.Read(buffer) - if err != nil { - return ErrSlaveClosed - } - - err = wt.handleSlaveReadEvent(buffer[:n]) - if err != nil { - return err - } + grp.Go(func() error { + buffer := make([]byte, wt.bufferSize) + for { + select { + case <-done: + return grpCtx.Err() + default: } - }() - }() - go func() { - errs <- func() error { - buffer := make([]byte, wt.bufferSize) - for { - n, err := wt.masterConn.Read(buffer) - if err != nil { - return ErrMasterClosed - } - - err = wt.handleMasterReadEvent(buffer[:n]) - if err != nil { - return err - } + n, err := wt.slave.Read(buffer) + if err != nil { + return ErrSlaveClosed } - }() - }() - select { - case <-ctx.Done(): - err = ctx.Err() - case err = <-errs: - } + err = wt.handleSlaveReadEvent(buffer[:n]) + if err != nil { + return err + } + } + }) - return err + grp.Go(func() error { + buffer := make([]byte, wt.bufferSize) + for { + select { + case <-done: + return grpCtx.Err() + default: + } + + n, err := wt.masterConn.Read(buffer) + if err != nil { + return ErrMasterClosed + } + + err = wt.handleMasterReadEvent(buffer[:n]) + if err != nil { + return err + } + } + }) + + return grp.Wait() } func (wt *WebTTY) sendInitializeMessage() error { @@ -205,7 +209,8 @@ func (wt *WebTTY) handleMasterReadEvent(data []byte) error { columns = int(args.Columns) } - wt.slave.ResizeTerminal(columns, rows) + // Ignoring this error unfournately + _ = wt.slave.ResizeTerminal(columns, rows) default: return errors.Errorf("unknown message type `%c`", data[0]) }