mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
fix: atomic.Value should be a concrete type to avoid panics (#13740)
Go's atomic.Value does not support `nil` type, concrete type is necessary to avoid any panics with the current implementation. Also remove boolean to turn-off tracking of freezeCount.
This commit is contained in:
parent
91e0823ff0
commit
9ca25bd48f
@ -228,7 +228,7 @@ func (t *apiConfig) getRequestsPool() (chan struct{}, time.Duration) {
|
||||
func maxClients(f http.HandlerFunc) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if val := globalServiceFreeze.Load(); val != nil {
|
||||
if unlock, ok := val.(chan struct{}); ok {
|
||||
if unlock, ok := val.(chan struct{}); ok && unlock != nil {
|
||||
// Wait until unfrozen.
|
||||
<-unlock
|
||||
}
|
||||
|
@ -68,56 +68,37 @@ func restartProcess() error {
|
||||
return syscall.Exec(argv0, os.Args, os.Environ())
|
||||
}
|
||||
|
||||
// Keep track of number of freeze/unfreeze calls.
|
||||
const trackFreezeCount = true
|
||||
|
||||
// freezeServices will freeze all incoming S3 API calls.
|
||||
// For each call, unfreezeServices must be called once.
|
||||
func freezeServices() {
|
||||
// Use atomics for globalServiceFreeze, so we can read without locking.
|
||||
if trackFreezeCount {
|
||||
// We need a lock since we are need the 2 atomic values to remain in sync.
|
||||
globalServiceFreezeMu.Lock()
|
||||
// If multiple calls, first one creates channel.
|
||||
globalServiceFreezeCnt++
|
||||
if globalServiceFreezeCnt == 1 {
|
||||
globalServiceFreeze.Store(make(chan struct{}))
|
||||
}
|
||||
globalServiceFreezeMu.Unlock()
|
||||
} else {
|
||||
// If multiple calls, first one creates channel.
|
||||
globalServiceFreeze.CompareAndSwap(nil, make(chan struct{}))
|
||||
// We need a lock since we are need the 2 atomic values to remain in sync.
|
||||
globalServiceFreezeMu.Lock()
|
||||
// If multiple calls, first one creates channel.
|
||||
globalServiceFreezeCnt++
|
||||
if globalServiceFreezeCnt == 1 {
|
||||
globalServiceFreeze.Store(make(chan struct{}))
|
||||
}
|
||||
globalServiceFreezeMu.Unlock()
|
||||
}
|
||||
|
||||
// unfreezeServices will unfreeze all incoming S3 API calls.
|
||||
// For each call, unfreezeServices must be called once.
|
||||
func unfreezeServices() {
|
||||
if trackFreezeCount {
|
||||
// We need a lock since we need the 2 atomic values to remain in sync.
|
||||
globalServiceFreezeMu.Lock()
|
||||
// Close when we reach 0
|
||||
globalServiceFreezeCnt--
|
||||
if globalServiceFreezeCnt <= 0 {
|
||||
// Ensure we only close once.
|
||||
if val := globalServiceFreeze.Load(); val != nil {
|
||||
if ch, ok := val.(chan struct{}); ok {
|
||||
globalServiceFreeze.Store(nil)
|
||||
close(ch)
|
||||
}
|
||||
}
|
||||
globalServiceFreezeCnt = 0 // Don't risk going negative.
|
||||
}
|
||||
globalServiceFreezeMu.Unlock()
|
||||
} else {
|
||||
// If multiple calls, first one closes channel.
|
||||
// We need a lock since we need the 2 atomic values to remain in sync.
|
||||
globalServiceFreezeMu.Lock()
|
||||
// Close when we reach 0
|
||||
globalServiceFreezeCnt--
|
||||
if globalServiceFreezeCnt <= 0 {
|
||||
// Ensure we only close once.
|
||||
if val := globalServiceFreeze.Load(); val != nil {
|
||||
var _ch chan struct{}
|
||||
if ch, ok := val.(chan struct{}); ok {
|
||||
// Ensure we only close once.
|
||||
if globalServiceFreeze.CompareAndSwap(val, nil) {
|
||||
close(ch)
|
||||
}
|
||||
globalServiceFreeze.Store(_ch)
|
||||
close(ch)
|
||||
}
|
||||
}
|
||||
globalServiceFreezeCnt = 0 // Don't risk going negative.
|
||||
}
|
||||
globalServiceFreezeMu.Unlock()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user