Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/20250818160732.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:bug: `subprocess` Make sure that cancellation can't enter deadlock
11 changes: 10 additions & 1 deletion utils/subprocess/monitoring.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ func newSubprocessMonitoring(parentCtx context.Context) *subprocessMonitoring {

// CancelSubprocess interrupts an on-going process.
func (s *subprocessMonitoring) CancelSubprocess() {
s.monitoringStopping.Store(true)
// Ensure we only ever run the cancel-store once and prevent the following deadlocks:
// 1. Some functions like Execute() do defer s.Cancel()
// 2. This calls subprocessMonitoring.CancelSubprocess() which calls cancelStore.Cancel() (acquiring mutex)
// 3. That Cancel() calls the context cancel func, which closes ProcessContext().Done()
// 4. The runProcessMonitoring blocks on ctx<-Done() and calls m.CancelSubprocess() again
// 5. This tries to run cancelStore.Cancel() a second time while the first Cancel() is still executing
// 6. go-deadlock detects deadlock
if s.monitoringStopping.Swap(true) {
return
}
s.cancelStore.Cancel()
}

Expand Down
Loading