-
Notifications
You must be signed in to change notification settings - Fork 803
fix(monitor): add missing lock in Observe to prevent data race #2588
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
0fbbc17
c1fda4b
ec23b35
09581a2
f7a05d0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,7 +71,15 @@ func CheckPriority(utSwitchOn map[string]UtilizationPerDevice, p int, c *nvidia. | |
| return false | ||
| } | ||
|
|
||
| var observeTestHook func() | ||
|
|
||
| func Observe(lister *nvidia.ContainerLister) { | ||
| if observeTestHook != nil { | ||
| observeTestHook() | ||
| } | ||
| lister.Lock() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. pr #2311 hit a real deadlock adding a lock inside listcontainers, because metrics.go already holds the lock when it calls listcontainers. why does this lock here not hit the same issue?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue in #2311 happened because metrics.go already held the lock. When it called ListContainers(), adding a lock inside there made the exact same code try to lock it twice, which causes a deadlock. The lock here is safe because metrics.go never actually calls Observe(). Observe() only runs in its own separate background loop watchAndFeedback. Since they run totally separate from each other, they just wait their turn for the lock. No double-locking can happen here. @mesutoezdil hope you liked it |
||
| defer lister.UnLock() | ||
|
|
||
| utSwitchOn := map[string]UtilizationPerDevice{} | ||
| containers := lister.ListContainers() | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue #2573 says pod add/update informer events call update() at the same time as observe(). this file only registers deletefunc, and that one only logs, it never touches containers. where does the real concurrent write come from today? the lock is still correct and safe to add either way, just checking the reproduction story is accurate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue description doesn't quite get the informer events right.
Update()andObserve()just run sequentially on the ticker loop, so they don't race with each other.The real race is between
Observe()modifyingc.Infoin the background and Prometheus concurrently scraping the/metricsendpoint. SinceCollect()already grabs the lister lock when responding to Prometheus scrapes, grabbing the same lock inObserve()properly synchronizes the writes.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mesutoezdil I've answered your question inline! Let me know if you need anything else from my end.