1
0
mirror of https://github.com/v2fly/v2ray-core.git synced 2026-05-06 04:29:08 -04:00

fix goroutine leak in dynamic port

This commit is contained in:
Darien Raymond
2017-01-29 12:58:52 +01:00
parent ebf15aa6bb
commit bfcc75f5d1
5 changed files with 38 additions and 41 deletions

View File

@@ -1,6 +1,7 @@
package encoding_test
import (
"context"
"testing"
"v2ray.com/core/common/buf"
@@ -40,7 +41,8 @@ func TestRequestSerialization(t *testing.T) {
client := NewClientSession(protocol.DefaultIDHash)
client.EncodeRequestHeader(expectedRequest, buffer)
userValidator := vmess.NewTimedUserValidator(protocol.DefaultIDHash)
ctx, cancel := context.WithCancel(context.Background())
userValidator := vmess.NewTimedUserValidator(ctx, protocol.DefaultIDHash)
userValidator.Add(user)
server := NewServerSession(userValidator)
@@ -53,4 +55,5 @@ func TestRequestSerialization(t *testing.T) {
assert.Address(expectedRequest.Address).Equals(actualRequest.Address)
assert.Port(expectedRequest.Port).Equals(actualRequest.Port)
assert.Byte(byte(expectedRequest.Security)).Equals(byte(actualRequest.Security))
cancel()
}

View File

@@ -86,7 +86,7 @@ func New(ctx context.Context, config *Config) (*VMessInboundHandler, error) {
return nil, errors.New("VMess|Inbound: No space in context.")
}
allowedClients := vmess.NewTimedUserValidator(protocol.DefaultIDHash)
allowedClients := vmess.NewTimedUserValidator(ctx, protocol.DefaultIDHash)
for _, user := range config.User {
allowedClients.Add(user)
}

View File

@@ -6,11 +6,11 @@
package vmess
import (
"context"
"sync"
"time"
"v2ray.com/core/common/protocol"
"v2ray.com/core/common/signal"
)
const (
@@ -27,12 +27,11 @@ type idEntry struct {
type TimedUserValidator struct {
sync.RWMutex
running bool
ctx context.Context
validUsers []*protocol.User
userHash map[[16]byte]*indexTimePair
ids []*idEntry
hasher protocol.IDHash
cancel *signal.CancelSignal
}
type indexTimePair struct {
@@ -40,37 +39,18 @@ type indexTimePair struct {
timeSec protocol.Timestamp
}
func NewTimedUserValidator(hasher protocol.IDHash) protocol.UserValidator {
func NewTimedUserValidator(ctx context.Context, hasher protocol.IDHash) protocol.UserValidator {
tus := &TimedUserValidator{
ctx: ctx,
validUsers: make([]*protocol.User, 0, 16),
userHash: make(map[[16]byte]*indexTimePair, 512),
ids: make([]*idEntry, 0, 512),
hasher: hasher,
running: true,
cancel: signal.NewCloseSignal(),
}
go tus.updateUserHash(updateIntervalSec * time.Second)
return tus
}
func (v *TimedUserValidator) Release() {
if !v.running {
return
}
v.cancel.Cancel()
v.cancel.WaitForDone()
v.Lock()
defer v.Unlock()
if !v.running {
return
}
v.running = false
}
func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, idx int, entry *idEntry) {
var hashValue [16]byte
var hashValueRemoval [16]byte
@@ -93,9 +73,6 @@ func (v *TimedUserValidator) generateNewHashes(nowSec protocol.Timestamp, idx in
}
func (v *TimedUserValidator) updateUserHash(interval time.Duration) {
v.cancel.WaitThread()
defer v.cancel.FinishThread()
for {
select {
case now := <-time.After(interval):
@@ -105,7 +82,7 @@ func (v *TimedUserValidator) updateUserHash(interval time.Duration) {
v.generateNewHashes(nowSec, entry.userIdx, entry)
}
v.Unlock()
case <-v.cancel.WaitForCancel():
case <-v.ctx.Done():
return
}
}
@@ -151,9 +128,6 @@ func (v *TimedUserValidator) Get(userHash []byte) (*protocol.User, protocol.Time
defer v.RUnlock()
v.RLock()
if !v.running {
return nil, 0, false
}
var fixedSizeHash [16]byte
copy(fixedSizeHash[:], userHash)
pair, found := v.userHash[fixedSizeHash]