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
This commit is contained in:
lifenjoiner 2022-06-29 00:28:57 +08:00 committed by GitHub
parent 59ce17e0ab
commit 0e2bb13254
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 16 deletions

View File

@ -84,6 +84,7 @@ func handleColdStartClient(clientPc *net.UDPConn, cancelChannel chan struct{}, i
exit := false
select {
case <-cancelChannel:
cancelChannel <- struct{}{}
exit = true
default:
}
@ -95,6 +96,12 @@ func handleColdStartClient(clientPc *net.UDPConn, cancelChannel chan struct{}, i
}
if err != nil {
dlog.Warn(err)
select {
case <-cancelChannel:
cancelChannel <- struct{}{}
default:
cancelChannel = make(chan struct{}, 1)
}
return true
}
packet := buffer[:length]
@ -134,7 +141,6 @@ func addColdStartListener(
for !handleColdStartClient(clientPc, cancelChannel, ipsMap) {
}
clientPc.Close()
cancelChannel <- struct{}{}
}()
return nil
}

View File

@ -316,7 +316,7 @@ func DNSExchange(
) (*dns.Msg, time.Duration, bool, error) {
for {
cancelChannel := make(chan struct{})
channel := make(chan DNSExchangeResponse)
channel := make(chan DNSExchangeResponse, 6)
var err error
options := 0
@ -325,32 +325,32 @@ func DNSExchange(
queryCopy := query.Copy()
queryCopy.Id += uint16(options)
go func(query *dns.Msg, delay time.Duration) {
option := _dnsExchange(proxy, proto, query, serverAddress, relay, 1500)
time.Sleep(delay)
option := DNSExchangeResponse{err: errors.New("Canceled")}
select {
case <-cancelChannel:
default:
option = _dnsExchange(proxy, proto, query, serverAddress, relay, 1500)
}
option.fragmentsBlocked = false
option.priority = 0
channel <- option
time.Sleep(delay)
select {
case <-cancelChannel:
return
default:
}
}(queryCopy, time.Duration(200*tries)*time.Millisecond)
options++
}
queryCopy := query.Copy()
queryCopy.Id += uint16(options)
go func(query *dns.Msg, delay time.Duration) {
option := _dnsExchange(proxy, proto, query, serverAddress, relay, 480)
time.Sleep(delay)
option := DNSExchangeResponse{err: errors.New("Canceled")}
select {
case <-cancelChannel:
default:
option = _dnsExchange(proxy, proto, query, serverAddress, relay, 480)
}
option.fragmentsBlocked = true
option.priority = 1
channel <- option
time.Sleep(delay)
select {
case <-cancelChannel:
return
default:
}
}(queryCopy, time.Duration(250*tries)*time.Millisecond)
options++
}