[ 
https://issues.apache.org/jira/browse/YUNIKORN-3446?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

ASF GitHub Bot updated YUNIKORN-3446:
-------------------------------------
    Labels: pull-request-available  (was: )

> [UGM] Race condition in ensureGroupTrackerForApp creates duplicate 
> GroupTrackers and bypasses group quota
> ---------------------------------------------------------------------------------------------------------
>
>                 Key: YUNIKORN-3446
>                 URL: https://issues.apache.org/jira/browse/YUNIKORN-3446
>             Project: Apache YuniKorn
>          Issue Type: Bug
>          Components: core - scheduler
>            Reporter: Hedger Lai
>            Assignee: Hedger Lai
>            Priority: Major
>              Labels: pull-request-available
>
> h3. Problem Description
> In the User & Group Management (UGM) subsystem, when multiple applications 
> belonging to the same user and group are submitted concurrently, a race 
> condition in {{Manager.ensureGroupTrackerForApp}} causes multiple distinct 
> {{GroupTracker}} instances to be instantiated for the exact same group.
> As a result:
> 1. Applications become bound to different, orphaned {{GroupTracker}} 
> instances in memory.
> 2. The global {{Manager}} only tracks the last overwritten {{GroupTracker}}, 
> leaving the resource usage of earlier applications completely untracked at 
> the group level (*Silent Quota Bypass*).
> 3. When affected applications complete and call {{DecreaseTrackedResource}}, 
> the canonical {{GroupTracker}} in the manager fails to find the application, 
> causing state and metric inconsistencies.
> h3. Root Cause Analysis
> In {{pkg/scheduler/ugm/manager.go}} (lines 243-252):
> {code:go}
> if appGroup != common.Empty {
>     groupTracker = m.GetGroupTracker(appGroup) // Step 1: Read lock check
>     if groupTracker == nil {
>         groupTracker = newGroupTracker(appGroup, m.events) // Step 2: 
> Unsynchronized allocation
>         m.Lock()
>         m.groupTrackers[appGroup] = groupTracker // Step 3: Blind overwrite 
> without double check!
>         m.Unlock()
>     }
> }
> userTracker.setGroupForApp(applicationID, groupTracker) // Step 4: Bound to 
> app
> {code}
> This is a classic check-then-act / missing double-checked locking flaw:
> * Multiple concurrent goroutines calling {{IncreaseTrackedResource}} 
> concurrently see {{groupTracker == nil}}.
> * Goroutine 1 creates instance A and writes it into 
> {{m.groupTrackers[appGroup]}}.
> * Goroutine 2 creates instance B and blindly overwrites 
> {{m.groupTrackers[appGroup]}} with instance B.
> * Goroutine 1 binds instance A to its app, while Goroutine 2 binds instance B 
> to its app.
> In contrast, {{getUserTracker}} in the same file (line 628) correctly 
> synchronizes and double-checks {{m.userTrackers}} under the write lock, but 
> an equivalent safe {{getGroupTracker}} helper was never implemented.
> h3. Reproduce
> We verified this locally with a concurrent chaos test launching 50 
> applications under the same group simultaneously:
> {code:text}
> === RUN   TestEnsureGroupTrackerForAppConcurrentRace
>     manager_chaos_test.go:87: === CHAOS HARNESS TRIGGERED IN ROUND 2 ===
>     manager_chaos_test.go:88: Total applications launched: 50
>     manager_chaos_test.go:89: Distinct GroupTracker instances created in 
> memory: 3
>     manager_chaos_test.go:90: Applications linked to non-canonical orphaned 
> GroupTrackers: 3
>     manager_chaos_test.go:91: CRITICAL BUG DETECTED: Multiple GroupTracker 
> instances created for group 'devs'! Expected 1, found 3 instances (Round 2)
> --- FAIL: TestEnsureGroupTrackerForAppConcurrentRace (0.00s)
> {code}
> h3. Proposed Fix
> Implement a thread-safe private helper {{getGroupTracker(group string) 
> *GroupTracker}} in {{Manager}} that holds {{m.Lock()}} and checks existence 
> before allocating (mirroring {{getUserTracker}}), and invoke it inside 
> {{ensureGroupTrackerForApp}}.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to