Skip to content

Commit bb87722

Browse files
committed
Close Conn when given context is done
1 parent 9ca8fdc commit bb87722

2 files changed

Lines changed: 31 additions & 6 deletions

File tree

conn.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ var _ JSONRPC2 = (*Conn)(nil)
4444
// JSON-RPC protocol is symmetric, so a Conn runs on both ends of a
4545
// client-server connection.
4646
//
47-
// NewClient consumes conn, so you should call Close on the returned
48-
// client not on the given conn.
47+
// NewConn consumes stream, so you should call Close on the returned
48+
// Conn not on the given stream or its underlying connection.
49+
//
50+
// Conn is closed when the given context's Done channel is closed.
4951
func NewConn(ctx context.Context, stream ObjectStream, h Handler, opts ...ConnOpt) *Conn {
5052

5153
ctx, cancel := context.WithCancel(ctx)
@@ -65,6 +67,12 @@ func NewConn(ctx context.Context, stream ObjectStream, h Handler, opts ...ConnOp
6567
opt(c)
6668
}
6769
go c.readMessages(ctx)
70+
71+
go func() {
72+
<-ctx.Done()
73+
c.close(nil)
74+
}()
75+
6876
return c
6977
}
7078

conn_test.go

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,24 @@ import (
1515
)
1616

1717
func TestConn(t *testing.T) {
18+
19+
t.Run("closes when context is done", func(t *testing.T) {
20+
ctx, cancel := context.WithCancel(context.Background())
21+
22+
connA, connB := Pipe(ctx, noopHandler{}, noopHandler{})
23+
defer connA.Close()
24+
defer connB.Close()
25+
26+
cancel()
27+
<-connA.DisconnectNotify()
28+
29+
got := connA.Close()
30+
want := jsonrpc2.ErrClosed
31+
if got != want {
32+
t.Fatalf("got %v, want %v", got, want)
33+
}
34+
})
35+
1836
t.Run("cancels context when closed", func(t *testing.T) {
1937
ctxCanceled := make(chan struct{})
2038

@@ -24,7 +42,7 @@ func TestConn(t *testing.T) {
2442
close(ctxCanceled)
2543
})
2644

27-
connA, connB := Pipe(noopHandler{}, jsonrpc2.AsyncHandler(handler))
45+
connA, connB := Pipe(context.Background(), noopHandler{}, jsonrpc2.AsyncHandler(handler))
2846
defer connA.Close()
2947
defer connB.Close()
3048

@@ -232,7 +250,7 @@ func testParams(t *testing.T, want *json.RawMessage, fn func(c *jsonrpc2.Conn) e
232250
wg.Done()
233251
})
234252

235-
connA, connB := Pipe(noopHandler{}, handler)
253+
connA, connB := Pipe(context.Background(), noopHandler{}, handler)
236254
defer connA.Close()
237255
defer connB.Close()
238256

@@ -278,8 +296,7 @@ func assertRawJSONMessage(t *testing.T, got *json.RawMessage, want *json.RawMess
278296

279297
// Pipe returns two jsonrpc2.Conn, connected via a synchronous, in-memory, full
280298
// duplex network connection.
281-
func Pipe(handlerA, handlerB jsonrpc2.Handler) (connA *jsonrpc2.Conn, connB *jsonrpc2.Conn) {
282-
ctx := context.Background()
299+
func Pipe(ctx context.Context, handlerA, handlerB jsonrpc2.Handler) (connA *jsonrpc2.Conn, connB *jsonrpc2.Conn) {
283300
a, b := net.Pipe()
284301
connA = jsonrpc2.NewConn(ctx, jsonrpc2.NewPlainObjectStream(a), handlerA)
285302
connB = jsonrpc2.NewConn(ctx, jsonrpc2.NewPlainObjectStream(b), handlerB)

0 commit comments

Comments
 (0)