Skip to content

Commit 5ddf5de

Browse files
authored
Merge pull request multiformats#19 from libp2p/fix/close-on-err
improve correctness of closing connections on failure
2 parents 773b63c + 8467c1e commit 5ddf5de

File tree

2 files changed

+61
-19
lines changed

2 files changed

+61
-19
lines changed

listener_test.go

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ var _ = Describe("Listener", func() {
104104

105105
It("accepts a single connection", func() {
106106
ln := createListener(defaultUpgrader)
107+
defer ln.Close()
107108
cconn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(1))
108109
Expect(err).ToNot(HaveOccurred())
109110
sconn, err := ln.Accept()
@@ -113,6 +114,7 @@ var _ = Describe("Listener", func() {
113114

114115
It("accepts multiple connections", func() {
115116
ln := createListener(defaultUpgrader)
117+
defer ln.Close()
116118
const num = 10
117119
for i := 0; i < 10; i++ {
118120
cconn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(1))
@@ -127,11 +129,15 @@ var _ = Describe("Listener", func() {
127129
const timeout = 200 * time.Millisecond
128130
tpt.AcceptTimeout = timeout
129131
ln := createListener(defaultUpgrader)
132+
defer ln.Close()
130133
conn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
131-
Expect(err).ToNot(HaveOccurred())
134+
if !Expect(err).ToNot(HaveOccurred()) {
135+
return
136+
}
132137
done := make(chan struct{})
133138
go func() {
134139
defer GinkgoRecover()
140+
defer conn.Close()
135141
str, err := conn.OpenStream()
136142
Expect(err).ToNot(HaveOccurred())
137143
// start a Read. It will block until the connection is closed
@@ -151,10 +157,16 @@ var _ = Describe("Listener", func() {
151157
done := make(chan struct{})
152158
go func() {
153159
defer GinkgoRecover()
154-
_, _ = ln.Accept()
160+
conn, err := ln.Accept()
161+
if !Expect(err).To(HaveOccurred()) {
162+
conn.Close()
163+
}
155164
close(done)
156165
}()
157-
_, _ = dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
166+
conn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
167+
if !Expect(err).To(HaveOccurred()) {
168+
conn.Close()
169+
}
158170
Consistently(done).ShouldNot(BeClosed())
159171
// make the goroutine return
160172
ln.Close()
@@ -178,6 +190,7 @@ var _ = Describe("Listener", func() {
178190
if err != nil {
179191
return
180192
}
193+
conn.Close()
181194
accepted <- conn
182195
}
183196
}()
@@ -187,8 +200,14 @@ var _ = Describe("Listener", func() {
187200
wg.Add(1)
188201
go func() {
189202
defer GinkgoRecover()
190-
_, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
191-
Expect(err).ToNot(HaveOccurred())
203+
conn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
204+
if Expect(err).ToNot(HaveOccurred()) {
205+
stream, err := conn.AcceptStream() // wait for conn to be accepted.
206+
if !Expect(err).To(HaveOccurred()) {
207+
stream.Close()
208+
}
209+
conn.Close()
210+
}
192211
wg.Done()
193212
}()
194213
}
@@ -201,29 +220,40 @@ var _ = Describe("Listener", func() {
201220

202221
It("stops setting up when the more than AcceptQueueLength connections are waiting to get accepted", func() {
203222
ln := createListener(defaultUpgrader)
223+
defer ln.Close()
224+
204225
// setup AcceptQueueLength connections, but don't accept any of them
205-
dialed := make(chan struct{}, 10*st.AcceptQueueLength) // used as a thread-safe counter
226+
dialed := make(chan tpt.Conn, 10*st.AcceptQueueLength) // used as a thread-safe counter
206227
for i := 0; i < st.AcceptQueueLength; i++ {
207228
go func() {
208229
defer GinkgoRecover()
209-
_, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
230+
conn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
210231
Expect(err).ToNot(HaveOccurred())
211-
dialed <- struct{}{}
232+
dialed <- conn
212233
}()
213234
}
214235
Eventually(dialed).Should(HaveLen(st.AcceptQueueLength))
215236
// dial a new connection. This connection should not complete setup, since the queue is full
216237
go func() {
217238
defer GinkgoRecover()
218-
_, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
239+
conn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
219240
Expect(err).ToNot(HaveOccurred())
220-
dialed <- struct{}{}
241+
dialed <- conn
221242
}()
222243
Consistently(dialed).Should(HaveLen(st.AcceptQueueLength))
223244
// accept a single connection. Now the new connection should be set up, and fill the queue again
224-
_, err := ln.Accept()
225-
Expect(err).ToNot(HaveOccurred())
245+
conn, err := ln.Accept()
246+
if Expect(err).ToNot(HaveOccurred()) {
247+
conn.Close()
248+
}
226249
Eventually(dialed).Should(HaveLen(st.AcceptQueueLength + 1))
250+
251+
// Cleanup
252+
for i := 0; i < st.AcceptQueueLength+1; i++ {
253+
if c := <-dialed; c != nil {
254+
c.Close()
255+
}
256+
}
227257
})
228258
})
229259

@@ -233,9 +263,12 @@ var _ = Describe("Listener", func() {
233263
done := make(chan struct{})
234264
go func() {
235265
defer GinkgoRecover()
236-
_, err := ln.Accept()
237-
Expect(err).To(HaveOccurred())
238-
Expect(err.Error()).To(ContainSubstring("use of closed network connection"))
266+
conn, err := ln.Accept()
267+
if Expect(err).To(HaveOccurred()) {
268+
Expect(err.Error()).To(ContainSubstring("use of closed network connection"))
269+
} else {
270+
conn.Close()
271+
}
239272
close(done)
240273
}()
241274
Consistently(done).ShouldNot(BeClosed())
@@ -246,15 +279,20 @@ var _ = Describe("Listener", func() {
246279
It("doesn't accept new connections when it is closed", func() {
247280
ln := createListener(defaultUpgrader)
248281
Expect(ln.Close()).To(Succeed())
249-
_, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(1))
250-
Expect(err).To(HaveOccurred())
282+
conn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(1))
283+
if !Expect(err).To(HaveOccurred()) {
284+
conn.Close()
285+
}
251286
})
252287

253288
It("closes incoming connections that have not yet been accepted", func() {
254289
ln := createListener(defaultUpgrader)
255290
conn, err := dial(defaultUpgrader, ln.Multiaddr(), peer.ID(2))
291+
if !Expect(err).ToNot(HaveOccurred()) {
292+
ln.Close()
293+
return
294+
}
256295
Expect(conn.IsClosed()).To(BeFalse())
257-
Expect(err).ToNot(HaveOccurred())
258296
Expect(ln.Close()).To(Succeed())
259297
Eventually(conn.IsClosed).Should(BeTrue())
260298
})

upgrader.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func (u *Upgrader) upgrade(ctx context.Context, t transport.Transport, maconn ma
8989
}
9090
smconn, err := u.setupMuxer(ctx, sconn, p)
9191
if err != nil {
92-
conn.Close()
92+
sconn.Close()
9393
return nil, fmt.Errorf("failed to negotiate security stream multiplexer: %s", err)
9494
}
9595
return &transportConn{
@@ -122,6 +122,10 @@ func (u *Upgrader) setupMuxer(ctx context.Context, conn net.Conn, p peer.ID) (sm
122122
case <-done:
123123
return smconn, err
124124
case <-ctx.Done():
125+
// interrupt this process
126+
conn.Close()
127+
// wait to finish
128+
<-done
125129
return nil, ctx.Err()
126130
}
127131
}

0 commit comments

Comments
 (0)