Skip to content

fix(scheduler): serialize Filter device selection to prevent double GPU allocation - #2470

Closed
yxxhero wants to merge 1 commit into
Project-HAMi:masterfrom
yxxhero:fix/issue-2232-concurrent-device-double-allocation
Closed

fix(scheduler): serialize Filter device selection to prevent double GPU allocation#2470
yxxhero wants to merge 1 commit into
Project-HAMi:masterfrom
yxxhero:fix/issue-2232-concurrent-device-double-allocation

Conversation

@yxxhero

@yxxhero yxxhero commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

What type of PR is this?
/kind bug

What this PR does / why we need it:

Fixes #2232并发创建 pod 情况下,存在 pod 中卡 id 的注解和实际 pod 中使用卡的 id 不一致问题 (under concurrent pod creation, the GPU id annotated on a pod is inconsistent with the GPU id the pod actually uses).

The reported consequence is duplicate card allocation: the shared card gets over-allocated (causing OOM) while other idle cards cannot be handed out.

Root cause

The scheduler extender is served over HTTP with one goroutine per request and provides no cross-request serialization guarantee. In Filter, the device-selection critical section was not atomic:

  1. read node usage (getNodesUsage)
  2. pick the best node/device (calcScore)
  3. commit the reservation to the pod cache (podManager.AddPod)
  4. publish the allocation onto the pod annotation (PatchPodAnnotations)

Under concurrent pod creation (e.g. a multi-replica Deployment), two Filter calls can both read the same free GPU in step 1 before either commits it in step 3, so both pods are annotated with the same card id.

In the normal kube-scheduler flow scheduling cycles are already serialized, which is why the problem only surfaces under concurrent/re-entrant extender requests.

Fix

Add a filterLock and move the in-memory critical section (steps 1–3) into a selectAndCommitDevice helper that owns the lock through a single defer Unlock, so two pods can never reserve the same device. The lock is released before step 4 (PatchPodAnnotations), so concurrent Filters are never blocked on the apiserver round trip; the on-failure rollback runs outside the lock and is safe because the pod/quota managers have their own locks. The simulation path (filterSimulation) does not reserve devices and is unchanged.

This keeps the change minimal — it does not move reservation from Filter to Bind (the larger redesign from #2273 is tracked via the #2264 design discussion).

Test

  • Test_Filter_ConcurrentNoDoubleAllocation fires 8 pods at Filter simultaneously and asserts each is annotated with a distinct device id. Without the lock it reliably reports device device-7 double-allocated to pod pod-0 and pod pod-2; with the lock it passes (-race).
  • Test_Filter_RollbackOnPatchFailure verifies the cache reservation is rolled back when the annotation patch fails.

Validation

Scoped to the scheduler extender, so per CONTRIBUTING's hardware-validation gate this is validated with unit tests (including a -race regression test) rather than physical GPU hardware. make verify (license, import-aliases, golangci-lint) and go test -race ./pkg/scheduler/... pass locally.

Which issue(s) this PR fixes:
Fixes #2232

Special notes for your reviewer:

  • A single defer Unlock in the helper means any early return added there in future can never leak the lock.
  • A per-pod-UID lock was considered but not added: kube-scheduler runs one scheduling cycle at a time, so a pod UID is not filtered concurrently; the reproduced race is between different pods, which the global filterLock closes.

Does this PR introduce a user-facing change?

Fixed a race in the scheduler extender's Filter that could assign the same GPU to multiple pods created concurrently (e.g. a multi-replica Deployment), causing duplicate card allocation and OOM. Device allocation in Filter is now serialized.

AI assistance disclosure:
This PR was written with AI assistance for codebase analysis, implementation and test generation. I reviewed, built and tested the change myself (make verify, go test -race) and can explain the locking semantics. Per CONTRIBUTING.md, disclosure belongs in the PR description only — no AI co-author trailers are used.

Summary by CodeRabbit

  • Bug Fixes

    • Prevented concurrent scheduling operations from assigning the same GPU to multiple pods.
    • Improved consistency of device usage tracking, scoring, reservations, cache updates, and pod annotations during live scheduling.
    • Released tentative GPU reservations when pod annotation updates fail.
    • Reduced the risk of conflicting GPU allocations when multiple pods are scheduled simultaneously.
  • Tests

    • Added coverage verifying distinct GPU assignments during concurrent scheduling.
    • Added coverage confirming failed annotation updates return an error and remove tentative reservations.

@hami-robot hami-robot Bot added kind/bug Something isn't working dco-signoff: yes labels Aug 8, 2026
@hami-robot

hami-robot Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: yxxhero
Once this PR has been reviewed and has the lgtm label, please assign wawa0210 for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@hami-robot hami-robot Bot added the size/L label Aug 8, 2026
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The scheduler now serializes live Filter device selection and reservation. Pod annotation calls occur outside the lock. Annotation failures remove tentative reservations. Tests cover concurrent distinct allocation and rollback.

Changes

Concurrent allocation serialization

Layer / File(s) Summary
Serialize live device allocation
pkg/scheduler/scheduler.go
Scheduler.Filter protects usage reads, scoring, selection, reservations, and quota updates with filterLock. It publishes annotations after releasing the lock and rolls back reservations on annotation failure.
Validate concurrent allocation
pkg/scheduler/scheduler_test.go
The test runs eight concurrent filters against eight single-pod-capacity GPUs and verifies complete, distinct assignments.
Validate annotation rollback
pkg/scheduler/scheduler_test.go
The test induces an annotation patch failure, checks the returned error, and confirms that the reservation is absent from the pod cache.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • Project-HAMi/HAMi#2044: Both changes modify Scheduler.Filter reservation and rollback handling after annotation failure.

Suggested reviewers: mesutoezdil

Poem

A rabbit guards the GPU queue,
Each pod gets one slot, fair and true.
Failed notes release their claim,
Eight tests check each allocation name.
The scheduler keeps its pace.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: serializing device selection in Filter to prevent duplicate GPU allocation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai
coderabbitai Bot requested a review from peachest August 8, 2026 08:49
@yxxhero
yxxhero force-pushed the fix/issue-2232-concurrent-device-double-allocation branch from 59dc10d to 7ca3560 Compare August 8, 2026 08:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
pkg/scheduler/scheduler_test.go (2)

1454-1462: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Stop the informer factory when the test ends.

The test starts the informer factory at Line 1461 but never closes s.stopCh. The informer goroutines keep running for the rest of the package test run. Leaked goroutines make -race reports harder to attribute, because a failure can surface during an unrelated later test.

Add the channel close to the cleanup. Register it before the factory starts so cleanup order stays correct.

♻️ Proposed cleanup for the informer goroutines
 	client.KubeClient = fake.NewClientset()
 	t.Cleanup(func() { client.KubeClient = nil })
 	s := NewScheduler()
+	t.Cleanup(func() { close(s.stopCh) })
 	s.kubeClient = client.KubeClient
 	informerFactory := informers.NewSharedInformerFactoryWithOptions(client.KubeClient, time.Hour)

Based on learnings from the coding guidelines: "Unit tests should be runnable with the race detector and repository test conventions, such as go test ... -short --race -count=1."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/scheduler/scheduler_test.go` around lines 1454 - 1462, Update the test
setup around NewScheduler and informerFactory.Start to register cleanup that
closes s.stopCh before starting the informer factory, alongside the existing
KubeClient cleanup. Preserve the current cleanup behavior while ensuring
informer goroutines stop when the test ends.

Source: Coding guidelines


1521-1530: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Record the Filter errors instead of discarding them.

Line 1526 discards the error. If Filter fails for every pod, the test still fails, but it fails at Line 1540 with "has no allocated device". That message hides the real cause. Collect the errors per index and assert them after wg.Wait(), so a setup failure is distinguishable from a duplicate allocation.

♻️ Proposed error capture
 	start := make(chan struct{})
 	var wg sync.WaitGroup
+	filterErrs := make([]error, numPods)
 	for i := range numPods {
 		wg.Add(1)
-		go func(pod *corev1.Pod) {
+		go func(idx int, pod *corev1.Pod) {
 			defer wg.Done()
 			<-start
-			_, _ = s.Filter(extenderv1.ExtenderArgs{Pod: pod, NodeNames: &nodeNames})
-		}(pods[i])
+			_, filterErrs[idx] = s.Filter(extenderv1.ExtenderArgs{Pod: pod, NodeNames: &nodeNames})
+		}(i, pods[i])
 	}
 	close(start)
 	wg.Wait()
+	for i, err := range filterErrs {
+		require.NoError(t, err, "Filter failed for pod-%d", i)
+	}

Each goroutine writes a distinct slice index, so this stays race-free under -race.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/scheduler/scheduler_test.go` around lines 1521 - 1530, Update the
concurrent Filter test around s.Filter to retain each goroutine’s error in a
per-pod indexed collection instead of discarding it. After wg.Wait(), assert the
collected errors before checking device allocation results, preserving distinct
error reporting and race-free writes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/scheduler/config/config.go`:
- Around line 282-284: Make InitDevicesWithConfig atomic by collecting device
registrations in local maps or slices while running all initializers, then
assign device.DevicesMap and device.DevicesToHandle only after every initializer
succeeds. On any initializer error, leave both globals empty or restore their
prior state so InitDevices and InitDefaultDevices can retry without exposing
partial registrations.

In `@pkg/scheduler/scheduler.go`:
- Around line 923-930: The live Filter path currently holds filterLock while
calling util.PatchPodAnnotations, serializing concurrent requests across the
apiserver round trip. Restructure the flow around Filter and filterSimulation so
only non-blocking cache reservation/rollback mutations occur under filterLock;
release the lock before PatchPodAnnotations, then perform annotation patching
and any required rollback without reacquiring the global lock during the network
call. Preserve the existing atomic reservation behavior and simulation path.

---

Nitpick comments:
In `@pkg/scheduler/scheduler_test.go`:
- Around line 1454-1462: Update the test setup around NewScheduler and
informerFactory.Start to register cleanup that closes s.stopCh before starting
the informer factory, alongside the existing KubeClient cleanup. Preserve the
current cleanup behavior while ensuring informer goroutines stop when the test
ends.
- Around line 1521-1530: Update the concurrent Filter test around s.Filter to
retain each goroutine’s error in a per-pod indexed collection instead of
discarding it. After wg.Wait(), assert the collected errors before checking
device allocation results, preserving distinct error reporting and race-free
writes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 026da7d9-8cef-446b-b606-150d9cb6d429

📥 Commits

Reviewing files that changed from the base of the PR and between 3616313 and 59dc10d.

📒 Files selected for processing (6)
  • cmd/scheduler/main.go
  • pkg/scheduler/config/config.go
  • pkg/scheduler/config/config_test.go
  • pkg/scheduler/nodes_test.go
  • pkg/scheduler/scheduler.go
  • pkg/scheduler/scheduler_test.go

Comment thread pkg/scheduler/config/config.go Outdated
Comment on lines +282 to +284
if len(device.DevicesMap) > 0 {
klog.Info("Devices are already initialized, skipping initialization")
return
return nil

@coderabbitai coderabbitai Bot Aug 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Make device initialization atomic on failure.

InitDevicesWithConfig populates device.DevicesMap and device.DevicesToHandle while it iterates. If a later initializer fails, it returns an error but leaves earlier registrations in both globals. InitDevices then sees a non-empty device.DevicesMap and skips a retry. InitDefaultDevices also returns while exposing the partial registry. Build the registrations locally and assign both globals only after all initializers succeed, or clear both globals before returning the error.

Also applies to: 292-295, 461-464

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/scheduler/config/config.go` around lines 282 - 284, Make
InitDevicesWithConfig atomic by collecting device registrations in local maps or
slices while running all initializers, then assign device.DevicesMap and
device.DevicesToHandle only after every initializer succeeds. On any initializer
error, leave both globals empty or restore their prior state so InitDevices and
InitDefaultDevices can retry without exposing partial registrations.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of scope for this PR — pkg/scheduler/config/config.go is not touched here. Happy to open a separate PR for the InitDevicesWithConfig partial-registration cleanup if the maintainers want it.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yxxhero, acknowledged. This does not block the scheduler allocation race fix in #2470.

Would you like me to create a follow-up GitHub issue for atomic InitDevicesWithConfig registration in pkg/scheduler/config/config.go?

You are interacting with an AI system.

Comment thread pkg/scheduler/scheduler.go Outdated
@codecov

codecov Bot commented Aug 8, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.71429% with 5 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/scheduler/scheduler.go 85.71% 4 Missing and 1 partial ⚠️
Flag Coverage Δ
unittests 64.33% <85.71%> (+0.12%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/scheduler/scheduler.go 70.59% <85.71%> (+1.96%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@yxxhero
yxxhero force-pushed the fix/issue-2232-concurrent-device-double-allocation branch from 91785b2 to 99a8c12 Compare August 8, 2026 09:20
@maishivamhoo123

Copy link
Copy Markdown
Member

@yxxhero please read the contribution.md before raising a pr https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md and please disclose if you use any AI Assistance .

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/scheduler/scheduler.go`:
- Around line 983-991: The Filter flow must serialize requests for the same pod
UID across reservation selection, PatchPodAnnotations, and failure rollback; add
or reuse a per-pod UID lock or reservation token around these operations. Keep
filterLock scoped only to global device selection so different pods can continue
patching concurrently, and ensure rollback removes only the reservation owned by
the failing request.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f7f11e24-9c17-4d6f-bf27-58e16fd2e4fe

📥 Commits

Reviewing files that changed from the base of the PR and between 91785b2 and 99a8c12.

📒 Files selected for processing (1)
  • pkg/scheduler/scheduler.go

Comment thread pkg/scheduler/scheduler.go Outdated
Comment thread pkg/scheduler/scheduler.go Outdated
lock sync.RWMutex
synced bool

// filterLock serializes the device-selection critical section in Filter

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please write short comments . otherwise the comments will be more than the code. and please read https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md before raising the pr.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — trimmed to one line:
// filterLock serializes device selection in Filter so concurrent requests cannot reserve the same device (issue #2232).

Comment thread pkg/scheduler/scheduler.go Outdated
"pod", klog.KObj(args.Pod),
"reason", "request does not contain full nodes",
"nodeNamesLen", nodeNamesLen(args.NodeNames))
// Device selection and cache commit are serialized inside a helper that

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here also.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done here too — the call-site and selectAndCommitDevice comments are now 1–2 lines each.

…PU allocation

Under concurrent pod creation (e.g. a multi-replica Deployment), two Filter
extender calls can run in separate goroutines and both observe the same free
GPU before either commits its reservation to the pod cache. Both pods then get
the same card id annotated, so the card id in the pod annotation no longer
matches the card the pod actually uses: the shared card gets over-allocated
(causing OOM) while other idle cards cannot be handed out. This is issue Project-HAMi#2232.

The scheduler extender is served over HTTP with one goroutine per request and
provides no cross-request serialization guarantee, so the read-pick-commit
sequence in Filter (read node usage -> pick devices -> commit to cache) must be
made atomic.

Add a filterLock and move the in-memory critical section into a
selectAndCommitDevice helper that owns the lock through a single deferred
Unlock (so a future early return can never leak it). The lock covers only
device selection and cache commit; the PatchPodAnnotations API call and the
on-failure rollback run outside it, so concurrent Filters are not blocked on
network I/O. The rollback is safe because the pod/quota managers have their own
locks. The simulation path does not reserve devices and is unchanged. In the
normal kube-scheduler flow scheduling cycles are already serialized, so this
lock is uncontended there; it only closes the window for concurrent extender
requests.

Tests:
- Test_Filter_ConcurrentNoDoubleAllocation fires many pods at Filter
  simultaneously and asserts each is annotated with a distinct device id. It
  reliably reproduces the double allocation without the lock and passes with it.
- Test_Filter_RollbackOnPatchFailure verifies the cache reservation is rolled
  back when the annotation patch fails.
Signed-off-by: yxxhero <aiopsclub@163.com>
@yxxhero
yxxhero force-pushed the fix/issue-2232-concurrent-device-double-allocation branch from 99a8c12 to b0aacdc Compare August 8, 2026 09:40
@yxxhero

yxxhero commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

@maishivamhoo123 thanks — I've read CONTRIBUTING.md.

  • Hardware validation gate: this change is scoped to the scheduler extender, so per the gate it's validated with unit tests (incl. a -race regression test) rather than physical GPUs. make verify (license, import-aliases, golangci-lint) and go test -race ./pkg/scheduler/... pass locally.
  • AI assistance: disclosed in the PR description — AI was used for codebase analysis, implementation and test generation; I reviewed, built and tested the change myself and can explain the locking semantics. No AI co-author trailers are used (gate 5).
  • Comments: shortened the filterLock / Filter / selectAndCommitDevice comments to 1–2 lines each (replies on the two inline threads).

@FouoF

FouoF commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

We can fix it or request the user use k8s >= 1.23 which is old enough. Need more discussion about lt.

@FouoF

FouoF commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

/hold

@mesutoezdil

Copy link
Copy Markdown
Contributor

You can view the relevant rule here.
https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md#contribution-gates
"4. Review replies. The reply you post must be written by you and must address the specific point raised. Verbatim or canned AI replies, or replies that do not engage the comment, lead to the PR being closed."

@spencercjh

spencercjh commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Independent black-box evidence supports this fix: the race is straightforward to reproduce against the real Extender HTTP path, not only with a fake-client test.

In an isolated k3d cluster I registered one mock GPU with count: 10, created 12 distinct GPU Pods pinned to that physical UUID, and added a scheduling gate so kube-scheduler could not serialize or bind them first. I then used each Pod's actual Kubernetes JSON to issue 12 concurrent /filter requests, each with only that node in nodeNames.

All 12 requests succeeded and all 12 Pods received the same physical-device allocation annotation. The Scheduler's live metric afterwards was:

hami_gpu_shared_count{device_uuid="GPU-MOCK-AGENT-0"} 12

This exceeds the mock card's count: 10; the associated namespace quota was also 12 × the requested memory/core amount. That is the same read-score-then-reserve TOCTOU window described in this PR. A global filterLock around selection and in-memory commit is therefore a directly justified minimal correction. The scheduling gate is only a test harness control; it prevents normal kube-scheduler serialization from hiding concurrent/re-entrant Extender behavior.

@yxxhero

yxxhero commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@spencercjh so why close this PR?

@spencercjh

spencercjh commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@yxxhero I think the HAMi community is currently experiencing a significant impact from AI, and several owners are finding it quite unbearable. Maybe you’ve been flagged as spam.

@yxxhero

yxxhero commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@FouoF @mesutoezdil Thanks for the thorough validation and the detailed black-box test! I want to clarify that the approach in this PR wasn’t just AI-generated boilerplate. It was the result of careful deliberation regarding the concurrency issues in the Extender path. The filterLock was specifically chosen as a deliberate, minimal fix to address the TOCTOU window, and I’m glad to see it holds up under your rigorous testing.

@yxxhero

yxxhero commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@spencercjh thanks so much.

@mesutoezdil

mesutoezdil commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

@FouoF @mesutoezdil Thanks for the thorough validation and the detailed black-box test! I want to clarify that the approach in this PR wasn’t just AI-generated boilerplate. It was the result of careful deliberation regarding the concurrency issues in the Extender path. The filterLock was specifically chosen as a deliberate, minimal fix to address the TOCTOU window, and I’m glad to see it holds up under your rigorous testing.

thx for your message.
we have some rules. one of them is:

"https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md#contribution-gates
4. Review replies. The reply you post must be written by you and must address the specific point raised. Verbatim or canned AI replies, or replies that do not engage the comment, lead to the PR being closed."

This rule is in place so that maintainers can communicate with a person and receive a direct, short, and clear answer to the specific question.

Bcs no one's native language is English, and no one has time to read long llm texts.

as i remember the reason was your this answer: "#2470 (comment)"

would you like to open new PR?

@yxxhero

yxxhero commented Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

@spencercjh hi. any better ideas for this issue? if so please open an new PR or I open new PR? thanks so much.

@mesutoezdil

Copy link
Copy Markdown
Contributor

This is not specific to an older Kubernetes release. The reproducer makes concurrent real HTTP calls to the Scheduler Extender Filter endpoint after holding the Pods behind scheduling gates; the race is entirely inside the Scheduler's own read-current-usage → choose-device → add-temporary-allocation sequence.

Kubernetes 1.23 and later do not provide an atomic transaction or a cross-request serialization guarantee for an Extender's Filter handlers. Concurrent scheduling requests can still reach those handlers, so upgrading Kubernetes alone cannot close this window. The Scheduler must make the capacity check and temporary reservation atomic (for example, with the proposed Filter lock or an equivalent reservation primitive), and retain a concurrent regression test.

I don't know why you're sharing long LLM responses as answers.
Again, reminder..
Answers must be written by human being.
You can view the relevant rule here.
https://github.com/Project-HAMi/HAMi/blob/master/CONTRIBUTING.md#contribution-gates
4. Review replies. The reply you post must be written by you and must address the specific point raised. Verbatim or canned AI replies, or replies that do not engage the comment, lead to the PR being closed.

@spencercjh

Copy link
Copy Markdown
Contributor

@mesutoezdil I'm sorry for taking up your time. I'll follow the community guidelines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

并发创建pod情况下,存在pod 中卡id的注解和实际pod中使用卡的id不一致问题

5 participants