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 {
|
func maxClients(f http.HandlerFunc) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
if val := globalServiceFreeze.Load(); val != nil {
|
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.
|
// Wait until unfrozen.
|
||||||
<-unlock
|
<-unlock
|
||||||
}
|
}
|
||||||
|
@ -68,56 +68,37 @@ func restartProcess() error {
|
|||||||
return syscall.Exec(argv0, os.Args, os.Environ())
|
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.
|
// freezeServices will freeze all incoming S3 API calls.
|
||||||
// For each call, unfreezeServices must be called once.
|
// For each call, unfreezeServices must be called once.
|
||||||
func freezeServices() {
|
func freezeServices() {
|
||||||
// Use atomics for globalServiceFreeze, so we can read without locking.
|
// 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.
|
||||||
// We need a lock since we are need the 2 atomic values to remain in sync.
|
globalServiceFreezeMu.Lock()
|
||||||
globalServiceFreezeMu.Lock()
|
// If multiple calls, first one creates channel.
|
||||||
// If multiple calls, first one creates channel.
|
globalServiceFreezeCnt++
|
||||||
globalServiceFreezeCnt++
|
if globalServiceFreezeCnt == 1 {
|
||||||
if globalServiceFreezeCnt == 1 {
|
globalServiceFreeze.Store(make(chan struct{}))
|
||||||
globalServiceFreeze.Store(make(chan struct{}))
|
|
||||||
}
|
|
||||||
globalServiceFreezeMu.Unlock()
|
|
||||||
} else {
|
|
||||||
// If multiple calls, first one creates channel.
|
|
||||||
globalServiceFreeze.CompareAndSwap(nil, make(chan struct{}))
|
|
||||||
}
|
}
|
||||||
|
globalServiceFreezeMu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// unfreezeServices will unfreeze all incoming S3 API calls.
|
// unfreezeServices will unfreeze all incoming S3 API calls.
|
||||||
// For each call, unfreezeServices must be called once.
|
// For each call, unfreezeServices must be called once.
|
||||||
func unfreezeServices() {
|
func unfreezeServices() {
|
||||||
if trackFreezeCount {
|
// We need a lock since we need the 2 atomic values to remain in sync.
|
||||||
// We need a lock since we need the 2 atomic values to remain in sync.
|
globalServiceFreezeMu.Lock()
|
||||||
globalServiceFreezeMu.Lock()
|
// Close when we reach 0
|
||||||
// Close when we reach 0
|
globalServiceFreezeCnt--
|
||||||
globalServiceFreezeCnt--
|
if globalServiceFreezeCnt <= 0 {
|
||||||
if globalServiceFreezeCnt <= 0 {
|
// Ensure we only close once.
|
||||||
// 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.
|
|
||||||
if val := globalServiceFreeze.Load(); val != nil {
|
if val := globalServiceFreeze.Load(); val != nil {
|
||||||
|
var _ch chan struct{}
|
||||||
if ch, ok := val.(chan struct{}); ok {
|
if ch, ok := val.(chan struct{}); ok {
|
||||||
// Ensure we only close once.
|
globalServiceFreeze.Store(_ch)
|
||||||
if globalServiceFreeze.CompareAndSwap(val, nil) {
|
close(ch)
|
||||||
close(ch)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
globalServiceFreezeCnt = 0 // Don't risk going negative.
|
||||||
}
|
}
|
||||||
|
globalServiceFreezeMu.Unlock()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user