kaijaytu commented on code in PR #1114:
URL: https://github.com/apache/yunikorn-core/pull/1114#discussion_r3695388996
##########
pkg/scheduler/objects/application.go:
##########
@@ -2162,6 +2164,18 @@ func (sa *Application) executeTerminatedCallback() {
}
}
+func (sa *Application) SetReservationReleasedCallback(callback func(released
int)) {
+ sa.Lock()
+ defer sa.Unlock()
+ sa.reservationReleasedCallback = callback
+}
+
+func (sa *Application) executeReservationReleasedCallback(released int) {
+ if released > 0 && sa.reservationReleasedCallback != nil {
+ go sa.reservationReleasedCallback(released)
Review Comment:
The goroutine is necessary to prevent a deadlock. Here's what I checked:
1. `decReservationCount` requires `pc.Lock()` (partition write lock):
- partition.go L1793-1796
2. `timeoutPlaceholderProcessing` holds `sa.Lock()` (application write lock)
for its entire duration:
- application.go L407-409: `sa.Lock()` with `defer sa.Unlock()`
3. The reverse lock order exists in `AddApplication`:
- partition.go L346: `pc.Lock()` with `defer pc.Unlock()`
- partition.go L404: calls `app.SetTerminatedCallback()` while still
holding `pc.Lock()`
- application.go L2153-2156: `SetTerminatedCallback` internally takes
`sa.Lock()`
- So: `pc.Lock()` -> `sa.Lock()`
4. If the callback were synchronous, `timeoutPlaceholderProcessing` would
create:
- `sa.Lock()` -> `pc.Lock()` (via callback -> `decReservationCount`)
This is a classic lock-ordering inversion:
- Thread A (AddApplication): pc.Lock() -> sa.Lock()
- Thread B (timeoutPlaceholderProcessing): sa.Lock() -> pc.Lock()
The partition struct comment (partition.go L71-80) explicitly documents this
constraint:
> "The partition write lock must not be held while manipulating an
application... If the partition write lock is held while manipulating an
application a deadlock could occur."
The `go` keyword breaks the nesting so `pc.Lock()` is never acquired while
`sa.Lock()` is held. This is the same reason `executeTerminatedCallback`
(application.go L2159-2161) uses `go` for `moveTerminatedApp`, which also takes
`pc.Lock()`.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]