Serialize changing the state of the expiration manager pointer and

calling emitMetrics from its own goroutine.

Fixes #694
This commit is contained in:
Jeff Mitchell 2015-10-12 16:33:54 -04:00
parent 794adcce14
commit 78b5fcdf51
3 changed files with 15 additions and 2 deletions

View File

@ -19,6 +19,7 @@ BUG FIXES:
* core: Fix upgrade path for leases created in `generic` prior to 0.3 [GH-673]
* core: Stale leader entries will now be reaped [GH-679]
* core: Using `mount-tune` on the auth/token path did not take effect. [GH-688]
* core: Fix a potential race condition when (un)sealing the vault with metrics enabled [GH-694]
MISC:

View File

@ -17,10 +17,10 @@ import (
"golang.org/x/crypto/openpgp/packet"
"github.com/armon/go-metrics"
"github.com/hashicorp/uuid"
"github.com/hashicorp/vault/audit"
"github.com/hashicorp/vault/helper/mlock"
"github.com/hashicorp/vault/helper/pgpkeys"
"github.com/hashicorp/uuid"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/physical"
"github.com/hashicorp/vault/shamir"
@ -243,6 +243,10 @@ type Core struct {
// metricsCh is used to stop the metrics streaming
metricsCh chan struct{}
// metricsMutex is used to prevent a race condition between
// metrics emission and sealing leading to a nil pointer
metricsMutex sync.Mutex
defaultLeaseTTL time.Duration
maxLeaseTTL time.Duration
@ -1651,7 +1655,11 @@ func (c *Core) emitMetrics(stopCh chan struct{}) {
for {
select {
case <-time.After(time.Second):
c.expiration.emitMetrics()
c.metricsMutex.Lock()
if c.expiration != nil {
c.expiration.emitMetrics()
}
c.metricsMutex.Unlock()
case <-stopCh:
return
}

View File

@ -77,6 +77,8 @@ func NewExpirationManager(router *Router, view *BarrierView, ts *TokenStore, log
// setupExpiration is invoked after we've loaded the mount table to
// initialize the expiration manager
func (c *Core) setupExpiration() error {
c.metricsMutex.Lock()
defer c.metricsMutex.Unlock()
// Create a sub-view
view := c.systemBarrierView.SubView(expirationSubPath)
@ -101,6 +103,8 @@ func (c *Core) stopExpiration() error {
if err := c.expiration.Stop(); err != nil {
return err
}
c.metricsMutex.Lock()
defer c.metricsMutex.Unlock()
c.expiration = nil
}
return nil