Skip to content

Commit 0e2bb13

Browse files
authored
Fix goroutines memory leak by unbuffered channel blocking (#2136)
* Use buffered channel to avoid goroutine hanging on A send on an unbuffered channel can proceed if a receiver is ready. * Balance captivePortalHandler.cancelChannels for Stop
1 parent 59ce17e commit 0e2bb13

2 files changed

Lines changed: 18 additions & 12 deletions

File tree

dnscrypt-proxy/coldstart.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ func handleColdStartClient(clientPc *net.UDPConn, cancelChannel chan struct{}, i
8484
exit := false
8585
select {
8686
case <-cancelChannel:
87+
cancelChannel <- struct{}{}
8788
exit = true
8889
default:
8990
}
@@ -95,6 +96,12 @@ func handleColdStartClient(clientPc *net.UDPConn, cancelChannel chan struct{}, i
9596
}
9697
if err != nil {
9798
dlog.Warn(err)
99+
select {
100+
case <-cancelChannel:
101+
cancelChannel <- struct{}{}
102+
default:
103+
cancelChannel = make(chan struct{}, 1)
104+
}
98105
return true
99106
}
100107
packet := buffer[:length]
@@ -134,7 +141,6 @@ func addColdStartListener(
134141
for !handleColdStartClient(clientPc, cancelChannel, ipsMap) {
135142
}
136143
clientPc.Close()
137-
cancelChannel <- struct{}{}
138144
}()
139145
return nil
140146
}

dnscrypt-proxy/dnsutils.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ func DNSExchange(
316316
) (*dns.Msg, time.Duration, bool, error) {
317317
for {
318318
cancelChannel := make(chan struct{})
319-
channel := make(chan DNSExchangeResponse)
319+
channel := make(chan DNSExchangeResponse, 6)
320320
var err error
321321
options := 0
322322

@@ -325,32 +325,32 @@ func DNSExchange(
325325
queryCopy := query.Copy()
326326
queryCopy.Id += uint16(options)
327327
go func(query *dns.Msg, delay time.Duration) {
328-
option := _dnsExchange(proxy, proto, query, serverAddress, relay, 1500)
329-
option.fragmentsBlocked = false
330-
option.priority = 0
331-
channel <- option
332328
time.Sleep(delay)
329+
option := DNSExchangeResponse{err: errors.New("Canceled")}
333330
select {
334331
case <-cancelChannel:
335-
return
336332
default:
333+
option = _dnsExchange(proxy, proto, query, serverAddress, relay, 1500)
337334
}
335+
option.fragmentsBlocked = false
336+
option.priority = 0
337+
channel <- option
338338
}(queryCopy, time.Duration(200*tries)*time.Millisecond)
339339
options++
340340
}
341341
queryCopy := query.Copy()
342342
queryCopy.Id += uint16(options)
343343
go func(query *dns.Msg, delay time.Duration) {
344-
option := _dnsExchange(proxy, proto, query, serverAddress, relay, 480)
345-
option.fragmentsBlocked = true
346-
option.priority = 1
347-
channel <- option
348344
time.Sleep(delay)
345+
option := DNSExchangeResponse{err: errors.New("Canceled")}
349346
select {
350347
case <-cancelChannel:
351-
return
352348
default:
349+
option = _dnsExchange(proxy, proto, query, serverAddress, relay, 480)
353350
}
351+
option.fragmentsBlocked = true
352+
option.priority = 1
353+
channel <- option
354354
}(queryCopy, time.Duration(250*tries)*time.Millisecond)
355355
options++
356356
}

0 commit comments

Comments
 (0)