Skip to content

Commit a605dcd

Browse files
committed
using a wrapper over net.Listener to ensure that Close does not accept any new connections
1 parent 6035e66 commit a605dcd

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

netmaster/daemon.go

+4
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ func (d *daemon) runLeader() {
214214

215215
log.Infof("Netmaster listening on %s", d.listenURL)
216216

217+
listener = ListenWrapper(listener)
218+
217219
// start server
218220
go server.Serve(listener)
219221

@@ -241,6 +243,8 @@ func (d *daemon) runFollower() {
241243
log.Fatalln(err)
242244
}
243245

246+
listener = ListenWrapper(listener)
247+
244248
// start server
245249
go server.Serve(listener)
246250

netmaster/netwrapper.go

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/***
2+
Copyright 2014 Cisco Systems Inc. All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
http://www.apache.org/licenses/LICENSE-2.0
8+
9+
Unless required by applicable law or agreed to in writing, software
10+
distributed under the License is distributed on an "AS IS" BASIS,
11+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
See the License for the specific language governing permissions and
13+
limitations under the License.
14+
*/
15+
16+
package main
17+
18+
import (
19+
"net"
20+
"sync"
21+
)
22+
23+
// ListenWrapper is a wrapper over net.Listener
24+
func ListenWrapper(l net.Listener) net.Listener {
25+
return &contivListener{
26+
Listener: l,
27+
cond: sync.NewCond(&sync.Mutex{})}
28+
}
29+
30+
type contivListener struct {
31+
net.Listener
32+
cond *sync.Cond
33+
refCnt int
34+
}
35+
36+
func (s *contivListener) incrementRef() {
37+
s.cond.L.Lock()
38+
s.refCnt++
39+
s.cond.L.Unlock()
40+
}
41+
42+
func (s *contivListener) decrementRef() {
43+
s.cond.L.Lock()
44+
s.refCnt--
45+
newRefs := s.refCnt
46+
s.cond.L.Unlock()
47+
if newRefs == 0 {
48+
s.cond.Broadcast()
49+
}
50+
}
51+
52+
// Accept is a wrapper over regular Accept call
53+
// which also maintains the refCnt
54+
func (s *contivListener) Accept() (net.Conn, error) {
55+
s.incrementRef()
56+
defer s.decrementRef()
57+
return s.Listener.Accept()
58+
}
59+
60+
// Close closes the contivListener.
61+
func (s *contivListener) Close() error {
62+
if err := s.Listener.Close(); err != nil {
63+
return err
64+
}
65+
66+
s.cond.L.Lock()
67+
for s.refCnt > 0 {
68+
s.cond.Wait()
69+
}
70+
s.cond.L.Unlock()
71+
return nil
72+
}

0 commit comments

Comments
 (0)