Skip to content

Commit 65b7540

Browse files
committed
Cleanup exit error handling
1 parent 62e1d92 commit 65b7540

File tree

5 files changed

+45
-19
lines changed

5 files changed

+45
-19
lines changed

client.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,7 @@ func (r remoteProcess) listen(ctx context.Context) {
156156
defer r.stderr.w.Close()
157157

158158
buf := make([]byte, maxMessageSize) // max size of one websocket message
159-
for {
160-
if err := ctx.Err(); err != nil {
161-
r.done <- xerrors.Errorf("process canceled: %w", err)
162-
break
163-
}
159+
for ctx.Err() == nil {
164160
_, payload, err := r.conn.Read(ctx)
165161
if err != nil {
166162
continue
@@ -195,7 +191,7 @@ func (r remoteProcess) listen(ctx context.Context) {
195191
return nil
196192
}
197193
}
198-
return nil
194+
return ctx.Err()
199195
})
200196

201197
err := eg.Wait()

client_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,31 @@ func TestRemoteExec(t *testing.T) {
8181
execer := RemoteExecer(ws)
8282
testExecer(ctx, t, execer)
8383
}
84+
85+
func TestRemoteExecFail(t *testing.T) {
86+
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
87+
defer cancel()
88+
89+
ws, server := mockConn(ctx, t)
90+
defer server.Close()
91+
92+
execer := RemoteExecer(ws)
93+
testExecerFail(ctx, t, execer)
94+
}
95+
96+
func testExecerFail(ctx context.Context, t *testing.T, execer Execer) {
97+
process, err := execer.Start(ctx, Command{
98+
Command: "ls",
99+
Args: []string{"/doesnotexist"},
100+
})
101+
assert.Success(t, "start local cmd", err)
102+
103+
go io.Copy(ioutil.Discard, process.Stderr())
104+
go io.Copy(ioutil.Discard, process.Stdout())
105+
106+
err = process.Wait()
107+
code, ok := err.(ExitError)
108+
assert.True(t, "is exit error", ok)
109+
assert.True(t, "exit code is nonzero", code.Code != 0)
110+
assert.Error(t, "wait for process to error", err)
111+
}

localexec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (l *localProcess) Stderr() io.Reader {
4242
func (l *localProcess) Wait() error {
4343
err := l.cmd.Wait()
4444
if exitErr, ok := err.(*exec.ExitError); ok {
45-
return &ExitError{
45+
return ExitError{
4646
Code: exitErr.ExitCode(),
4747
}
4848
}

localexec_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ func TestExitCode(t *testing.T) {
6767
assert.Success(t, "start local cmd", err)
6868

6969
err = process.Wait()
70-
exitErr, ok := err.(*ExitError)
71-
assert.True(t, "error is *ExitError", ok)
70+
exitErr, ok := err.(ExitError)
71+
assert.True(t, "error is ExitError", ok)
7272
assert.Equal(t, "exit error", exitErr.Code, 127)
7373
}
7474

server.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func Serve(ctx context.Context, c *websocket.Conn, execer Execer) error {
7171
return err
7272
}
7373

74-
sendPID(ctx, process.Pid(), wsNetConn)
74+
_ = sendPID(ctx, process.Pid(), wsNetConn)
7575

7676
var outputgroup errgroup.Group
7777
outputgroup.Go(func() error {
@@ -85,11 +85,11 @@ func Serve(ctx context.Context, c *websocket.Conn, execer Execer) error {
8585
defer wsNetConn.Close()
8686
_ = outputgroup.Wait()
8787
err = process.Wait()
88-
if exitErr, ok := err.(*ExitError); ok {
89-
sendExitCode(ctx, exitErr.Code, wsNetConn)
88+
if exitErr, ok := err.(ExitError); ok {
89+
_ = sendExitCode(ctx, exitErr.Code, wsNetConn)
9090
return
9191
}
92-
sendExitCode(ctx, 0, wsNetConn)
92+
_ = sendExitCode(ctx, 0, wsNetConn)
9393
}()
9494
case proto.TypeResize:
9595
if process == nil {
@@ -122,23 +122,25 @@ func Serve(ctx context.Context, c *websocket.Conn, execer Execer) error {
122122
}
123123
}
124124

125-
func sendExitCode(ctx context.Context, exitCode int, conn net.Conn) {
125+
func sendExitCode(ctx context.Context, exitCode int, conn net.Conn) error {
126126
header, err := json.Marshal(proto.ServerExitCodeHeader{
127127
Type: proto.TypeExitCode,
128128
ExitCode: exitCode,
129129
})
130130
if err != nil {
131-
return
131+
return err
132132
}
133-
proto.WithHeader(conn, header).Write(nil)
133+
_, err = proto.WithHeader(conn, header).Write(nil)
134+
return err
134135
}
135136

136-
func sendPID(ctx context.Context, pid int, conn net.Conn) {
137+
func sendPID(ctx context.Context, pid int, conn net.Conn) error {
137138
header, err := json.Marshal(proto.ServerPidHeader{Type: proto.TypePid, Pid: pid})
138139
if err != nil {
139-
return
140+
return err
140141
}
141-
proto.WithHeader(conn, header).Write(nil)
142+
_, err = proto.WithHeader(conn, header).Write(nil)
143+
return err
142144
}
143145

144146
func copyWithHeader(r io.Reader, w io.Writer, header proto.Header) error {

0 commit comments

Comments
 (0)