Skip to content

Commit 97396d9

Browse files
author
Michal Witkowski
authored
Merge pull request mwitkow#11 from mwitkow/fix-close-bug
Fix a channel closing bug
2 parents af55d61 + 3fcbd37 commit 97396d9

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

proxy/handler.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,11 @@ func (s *handler) handler(srv interface{}, serverStream grpc.ServerStream) error
7575
if err != nil {
7676
return err
7777
}
78+
// Explicitly *do not close* s2cErrChan and c2sErrChan, otherwise the select below will not terminate.
79+
// Channels do not have to be closed, it is just a control flow mechanism, see
80+
// https://groups.google.com/forum/#!msg/golang-nuts/pZwdYRGxCIk/qpbHxRRPJdUJ
7881
s2cErrChan := s.forwardServerToClient(serverStream, clientStream)
79-
defer close(s2cErrChan)
8082
c2sErrChan := s.forwardClientToServer(clientStream, serverStream)
81-
defer close(c2sErrChan)
8283
// We don't know which side is going to stop sending first, so we need a select between the two.
8384
for i := 0; i < 2; i++ {
8485
select {

proxy/handler_test.go

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,11 @@ func (s *assertingService) PingStream(stream pb.TestService_PingStreamServer) er
9999
type ProxyHappySuite struct {
100100
suite.Suite
101101

102-
serverListener net.Listener
103-
server *grpc.Server
104-
proxyListener net.Listener
105-
proxy *grpc.Server
102+
serverListener net.Listener
103+
server *grpc.Server
104+
proxyListener net.Listener
105+
proxy *grpc.Server
106+
serverClientConn *grpc.ClientConn
106107

107108
client *grpc.ClientConn
108109
testClient pb.TestServiceClient
@@ -121,6 +122,12 @@ func (s *ProxyHappySuite) TestPingEmptyCarriesClientMetadata() {
121122
require.Equal(s.T(), &pb.PingResponse{Value: pingDefaultValue, Counter: 42}, out)
122123
}
123124

125+
func (s *ProxyHappySuite) TestPingEmpty_StressTest() {
126+
for i := 0; i < 50; i++ {
127+
s.TestPingEmptyCarriesClientMetadata()
128+
}
129+
}
130+
124131
func (s *ProxyHappySuite) TestPingCarriesServerHeadersAndTrailers() {
125132
headerMd := make(metadata.MD)
126133
trailerMd := make(metadata.MD)
@@ -175,6 +182,12 @@ func (s *ProxyHappySuite) TestPingStream_FullDuplexWorks() {
175182
assert.Len(s.T(), trailerMd, 1, "PingList trailer headers user contain metadata")
176183
}
177184

185+
func (s *ProxyHappySuite) TestPingStream_StressTest() {
186+
for i := 0; i < 50; i++ {
187+
s.TestPingStream_FullDuplexWorks()
188+
}
189+
}
190+
178191
func (s *ProxyHappySuite) SetupSuite() {
179192
var err error
180193

@@ -189,7 +202,7 @@ func (s *ProxyHappySuite) SetupSuite() {
189202
pb.RegisterTestServiceServer(s.server, &assertingService{t: s.T()})
190203

191204
// Setup of the proxy's Director.
192-
proxyClientConn, err := grpc.Dial(s.serverListener.Addr().String(), grpc.WithInsecure(), grpc.WithCodec(proxy.Codec()))
205+
s.serverClientConn, err = grpc.Dial(s.serverListener.Addr().String(), grpc.WithInsecure(), grpc.WithCodec(proxy.Codec()))
193206
require.NoError(s.T(), err, "must not error on deferred client Dial")
194207
director := func(ctx context.Context, fullName string) (*grpc.ClientConn, error) {
195208
md, ok := metadata.FromContext(ctx)
@@ -198,7 +211,7 @@ func (s *ProxyHappySuite) SetupSuite() {
198211
return nil, grpc.Errorf(codes.PermissionDenied, "testing rejection")
199212
}
200213
}
201-
return proxyClientConn, nil
214+
return s.serverClientConn, nil
202215
}
203216
s.proxy = grpc.NewServer(
204217
grpc.CustomCodec(proxy.Codec()),
@@ -225,6 +238,14 @@ func (s *ProxyHappySuite) SetupSuite() {
225238
}
226239

227240
func (s *ProxyHappySuite) TearDownSuite() {
241+
if s.client != nil {
242+
s.client.Close()
243+
}
244+
if s.serverClientConn != nil {
245+
s.serverClientConn.Close()
246+
}
247+
// Close all transports so the logs don't get spammy.
248+
time.Sleep(10 * time.Millisecond)
228249
if s.proxy != nil {
229250
s.proxy.Stop()
230251
s.proxyListener.Close()
@@ -233,9 +254,6 @@ func (s *ProxyHappySuite) TearDownSuite() {
233254
s.server.Stop()
234255
s.serverListener.Close()
235256
}
236-
if s.client != nil {
237-
s.client.Close()
238-
}
239257
}
240258

241259
func TestProxyHappySuite(t *testing.T) {

0 commit comments

Comments
 (0)