mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-02 00:17:13 +00:00
fix(client): stop holding the inbound-lock registry mutex while waiting on one inbound
lockInbound acquired the global registry mutex and then blocked on the per-inbound mutex without releasing the registry first. A slow client operation holding one inbound's mutex (for example a bulk delete pushing to an unreachable node) made the next waiter park on that inbound while still holding the registry mutex, which in turn blocked lockInbound for every other inbound — freezing client mutations panel-wide. Release the registry mutex before taking the per-inbound lock.
This commit is contained in:
@@ -28,12 +28,12 @@ var (
|
|||||||
|
|
||||||
func lockInbound(inboundId int) *sync.Mutex {
|
func lockInbound(inboundId int) *sync.Mutex {
|
||||||
inboundMutationLocksMu.Lock()
|
inboundMutationLocksMu.Lock()
|
||||||
defer inboundMutationLocksMu.Unlock()
|
|
||||||
m, ok := inboundMutationLocks[inboundId]
|
m, ok := inboundMutationLocks[inboundId]
|
||||||
if !ok {
|
if !ok {
|
||||||
m = &sync.Mutex{}
|
m = &sync.Mutex{}
|
||||||
inboundMutationLocks[inboundId] = m
|
inboundMutationLocks[inboundId] = m
|
||||||
}
|
}
|
||||||
|
inboundMutationLocksMu.Unlock()
|
||||||
m.Lock()
|
m.Lock()
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// lockInbound must not hold the global registry mutex while it waits on a busy
|
||||||
|
// inbound's own mutex, otherwise one slow client operation on a single inbound
|
||||||
|
// freezes client mutations on every other inbound panel-wide.
|
||||||
|
func TestLockInboundReleasesRegistryMutexWhileWaiting(t *testing.T) {
|
||||||
|
const id = 990006
|
||||||
|
held := lockInbound(id)
|
||||||
|
|
||||||
|
parked := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
close(parked)
|
||||||
|
lockInbound(id).Unlock()
|
||||||
|
}()
|
||||||
|
<-parked
|
||||||
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
|
if !inboundMutationLocksMu.TryLock() {
|
||||||
|
held.Unlock()
|
||||||
|
t.Fatal("registry mutex is held while a lockInbound caller waits on a busy inbound")
|
||||||
|
}
|
||||||
|
inboundMutationLocksMu.Unlock()
|
||||||
|
held.Unlock()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user