core: Make shutdownDoneCh atomic (#18358)
When issuing a core.Shutdown(), it is common to background the shutdown request. This allows Vault to continue cleaning up, mainly to release the stateLock. This allows the shutdown to complete, but is inherently racy, so the core.shutdownDoneCh needs to be made atomic.
This commit is contained in:
parent
55b21f2012
commit
809a04c8b4
|
@ -311,8 +311,11 @@ type Core struct {
|
|||
keepHALockOnStepDown *uint32
|
||||
heldHALock physical.Lock
|
||||
|
||||
// shutdownDoneCh is used to notify when Shutdown() completes
|
||||
shutdownDoneCh chan struct{}
|
||||
// shutdownDoneCh is used to notify when core.Shutdown() completes.
|
||||
// core.Shutdown() is typically issued in a goroutine to allow Vault to
|
||||
// release the stateLock. This channel is marked atomic to prevent race
|
||||
// conditions.
|
||||
shutdownDoneCh *atomic.Value
|
||||
|
||||
// unlockInfo has the keys provided to Unseal until the threshold number of parts is available, as well as the operation nonce
|
||||
unlockInfo *unlockInformation
|
||||
|
@ -900,7 +903,7 @@ func CreateCore(conf *CoreConfig) (*Core, error) {
|
|||
clusterPeerClusterAddrsCache: cache.New(3*clusterHeartbeatInterval, time.Second),
|
||||
enableMlock: !conf.DisableMlock,
|
||||
rawEnabled: conf.EnableRaw,
|
||||
shutdownDoneCh: make(chan struct{}),
|
||||
shutdownDoneCh: new(atomic.Value),
|
||||
replicationState: new(uint32),
|
||||
atomicPrimaryClusterAddrs: new(atomic.Value),
|
||||
atomicPrimaryFailoverAddrs: new(atomic.Value),
|
||||
|
@ -942,6 +945,8 @@ func CreateCore(conf *CoreConfig) (*Core, error) {
|
|||
atomic.StoreUint32(c.sealed, 1)
|
||||
c.metricSink.SetGaugeWithLabels([]string{"core", "unsealed"}, 0, nil)
|
||||
|
||||
c.shutdownDoneCh.Store(make(chan struct{}))
|
||||
|
||||
c.allLoggers = append(c.allLoggers, c.logger)
|
||||
|
||||
c.router.logger = c.logger.Named("router")
|
||||
|
@ -1239,9 +1244,11 @@ func (c *Core) Shutdown() error {
|
|||
|
||||
c.stateLock.Lock()
|
||||
defer c.stateLock.Unlock()
|
||||
if c.shutdownDoneCh != nil {
|
||||
close(c.shutdownDoneCh)
|
||||
c.shutdownDoneCh = nil
|
||||
|
||||
doneCh := c.shutdownDoneCh.Load().(chan struct{})
|
||||
if doneCh != nil {
|
||||
close(doneCh)
|
||||
c.shutdownDoneCh.Store((chan struct{})(nil))
|
||||
}
|
||||
|
||||
return err
|
||||
|
@ -1258,7 +1265,7 @@ func (c *Core) ShutdownWait() error {
|
|||
|
||||
// ShutdownDone returns a channel that will be closed after Shutdown completes
|
||||
func (c *Core) ShutdownDone() <-chan struct{} {
|
||||
return c.shutdownDoneCh
|
||||
return c.shutdownDoneCh.Load().(chan struct{})
|
||||
}
|
||||
|
||||
// CORSConfig returns the current CORS configuration
|
||||
|
|
Loading…
Reference in New Issue