VAULT-8630 Fix goroutine leak from RLQ initialize (#17281)

* VAULT-8630 Fix goroutine leak from RLQ initialize

* VAULT-8630 Changelog

* VAULT-8630 additional nil check
This commit is contained in:
Violet Hynes 2022-09-22 15:59:53 -04:00 committed by GitHub
parent 7d09d5a653
commit 2b8d8a3c6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 0 deletions

3
changelog/17281.txt Normal file
View file

@ -0,0 +1,3 @@
```release-note:bug
core/quotas: Fix goroutine leak caused by the seal process not fully cleaning up Rate Limit Quotas.
```

View file

@ -358,6 +358,11 @@ func (m *Manager) QuotaNames(qType Type) ([]string, error) {
m.lock.RLock() m.lock.RLock()
defer m.lock.RUnlock() defer m.lock.RUnlock()
return m.quotaNamesLocked(qType)
}
// quotaNamesLocked returns the names of all the quota rules for a given type, and must be called with the lock
func (m *Manager) quotaNamesLocked(qType Type) ([]string, error) {
txn := m.db.Txn(false) txn := m.db.Txn(false)
iter, err := txn.Get(qType.String(), indexID) iter, err := txn.Get(qType.String(), indexID)
if err != nil { if err != nil {
@ -393,6 +398,11 @@ func (m *Manager) QuotaByName(qType string, name string) (Quota, error) {
m.lock.RLock() m.lock.RLock()
defer m.lock.RUnlock() defer m.lock.RUnlock()
return m.quotaByNameLocked(qType, name)
}
// quotaByNameLocked queries for a quota rule in the db for a given quota name, and must be called with the lock
func (m *Manager) quotaByNameLocked(qType string, name string) (Quota, error) {
txn := m.db.Txn(false) txn := m.db.Txn(false)
quotaRaw, err := txn.First(qType, indexName, name) quotaRaw, err := txn.First(qType, indexName, name)
@ -745,6 +755,23 @@ func (m *Manager) Reset() error {
// Must be called with the lock held // Must be called with the lock held
func (m *Manager) resetCache() error { func (m *Manager) resetCache() error {
names, err := m.quotaNamesLocked(TypeRateLimit)
if err != nil {
return err
}
for _, name := range names {
quota, err := m.quotaByNameLocked(TypeRateLimit.String(), name)
if err != nil {
return err
}
if quota != nil {
rlq := quota.(*RateLimitQuota)
err = rlq.store.Close(context.Background())
if err != nil {
return err
}
}
}
db, err := memdb.NewMemDB(dbSchema()) db, err := memdb.NewMemDB(dbSchema())
if err != nil { if err != nil {
return err return err