From d29f7f2c60846f348ec123d9a1a46b460e6747b5 Mon Sep 17 00:00:00 2001 From: Sean Smith Date: Mon, 11 May 2020 19:16:41 -0500 Subject: [PATCH 1/2] Restore term state on exit --- cmd/coder/shell.go | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/cmd/coder/shell.go b/cmd/coder/shell.go index 9abc828f..41a25ddd 100644 --- a/cmd/coder/shell.go +++ b/cmd/coder/shell.go @@ -8,12 +8,13 @@ import ( "time" "github.com/spf13/pflag" - "go.coder.com/cli" - "go.coder.com/flog" "golang.org/x/crypto/ssh/terminal" "golang.org/x/sys/unix" "golang.org/x/time/rate" + "go.coder.com/cli" + "go.coder.com/flog" + client "cdr.dev/coder-cli/internal/entclient" "cdr.dev/coder-cli/wush" ) @@ -30,14 +31,20 @@ func (cmd *shellCmd) Spec() cli.CommandSpec { } } -func enableTerminal(fd int) { - _, err := terminal.MakeRaw(fd) +func enableTerminal(fd int) (restore func()) { + state, err := terminal.MakeRaw(fd) if err != nil { flog.Fatal("make raw term: %v", err) } + return func() { + err := terminal.Restore(fd, state) + if err != nil { + flog.Fatal("restore term state: %v", err) + } + } } -func (cmd *shellCmd) sendResizeEvents(termfd int, client *wush.Client) { +func sendResizeEvents(termfd int, client *wush.Client) { sigs := make(chan os.Signal, 16) signal.Notify(sigs, unix.SIGWINCH) @@ -83,6 +90,11 @@ func (cmd *shellCmd) Run(fl *pflag.FlagSet) { args = []string{"-c", "exec $(getent passwd $(whoami) | awk -F: '{ print $7 }')"} } + exitCode := runCommand(envName, command, args) + os.Exit(exitCode) +} + +func runCommand(envName string, command string, args []string) int { var ( entClient = requireAuth() env = findEnv(entClient, envName) @@ -92,7 +104,8 @@ func (cmd *shellCmd) Run(fl *pflag.FlagSet) { tty := terminal.IsTerminal(termfd) if tty { - enableTerminal(termfd) + restore := enableTerminal(termfd) + defer restore() } conn, err := entClient.DialWush( @@ -108,10 +121,10 @@ func (cmd *shellCmd) Run(fl *pflag.FlagSet) { wc := wush.NewClient(ctx, conn) if tty { - go cmd.sendResizeEvents(termfd, wc) + go sendResizeEvents(termfd, wc) } - go func(){ + go func() { defer wc.Stdin.Close() io.Copy(wc.Stdin, os.Stdin) }() @@ -122,5 +135,6 @@ func (cmd *shellCmd) Run(fl *pflag.FlagSet) { if err != nil { flog.Fatal("wush error: %v", err) } - os.Exit(int(exitCode)) + + return int(exitCode) } From b93d6501d97986ca9fd8c77ba4ff334848d87b1c Mon Sep 17 00:00:00 2001 From: Sean Smith Date: Mon, 11 May 2020 19:29:27 -0500 Subject: [PATCH 2/2] Allow for proper terminal restore on error --- cmd/coder/shell.go | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/cmd/coder/shell.go b/cmd/coder/shell.go index 41a25ddd..e54c39bf 100644 --- a/cmd/coder/shell.go +++ b/cmd/coder/shell.go @@ -11,6 +11,7 @@ import ( "golang.org/x/crypto/ssh/terminal" "golang.org/x/sys/unix" "golang.org/x/time/rate" + "golang.org/x/xerrors" "go.coder.com/cli" "go.coder.com/flog" @@ -31,17 +32,17 @@ func (cmd *shellCmd) Spec() cli.CommandSpec { } } -func enableTerminal(fd int) (restore func()) { +func enableTerminal(fd int) (restore func(), err error) { state, err := terminal.MakeRaw(fd) if err != nil { - flog.Fatal("make raw term: %v", err) + return restore, xerrors.Errorf("make raw term: %w", err) } return func() { err := terminal.Restore(fd, state) if err != nil { - flog.Fatal("restore term state: %v", err) + flog.Error("restore term state: %v", err) } - } + }, nil } func sendResizeEvents(termfd int, client *wush.Client) { @@ -90,11 +91,14 @@ func (cmd *shellCmd) Run(fl *pflag.FlagSet) { args = []string{"-c", "exec $(getent passwd $(whoami) | awk -F: '{ print $7 }')"} } - exitCode := runCommand(envName, command, args) + exitCode, err := runCommand(envName, command, args) + if err != nil { + flog.Fatal("run command: %v", err) + } os.Exit(exitCode) } -func runCommand(envName string, command string, args []string) int { +func runCommand(envName string, command string, args []string) (int, error) { var ( entClient = requireAuth() env = findEnv(entClient, envName) @@ -104,7 +108,10 @@ func runCommand(envName string, command string, args []string) int { tty := terminal.IsTerminal(termfd) if tty { - restore := enableTerminal(termfd) + restore, err := enableTerminal(termfd) + if err != nil { + return -1, err + } defer restore() } @@ -115,7 +122,7 @@ func runCommand(envName string, command string, args []string) int { Stdin: true, }, command, args...) if err != nil { - flog.Fatal("dial wush: %v", err) + return -1, err } ctx := context.Background() @@ -133,8 +140,8 @@ func runCommand(envName string, command string, args []string) int { exitCode, err := wc.Wait() if err != nil { - flog.Fatal("wush error: %v", err) + return -1, err } - return int(exitCode) + return int(exitCode), nil }