From 8cc19911b1107a50c53593462b1cc37a38fcdfcb Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Tue, 29 Oct 2019 15:22:04 -0700 Subject: [PATCH] smart_status: move channel write outside lock to avoid deadlock The smartStatusOutput.done channel is read from a goroutine that locks smartStatusOutput.lock. If the goroutine that writes to smartStatusOutput.done is holding smartStatusOutput.lock it can lead to an AB-BA deadlock. Call stopActionTableTick from outside the lock. Fixes: 143558785 Test: none Change-Id: I93a10ef9ff16c3953a1c5ccb102b024158358fe4 --- ui/terminal/smart_status.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ui/terminal/smart_status.go b/ui/terminal/smart_status.go index efcfd4359..6bdf14074 100644 --- a/ui/terminal/smart_status.go +++ b/ui/terminal/smart_status.go @@ -170,6 +170,13 @@ func (s *smartStatusOutput) FinishAction(result status.ActionResult, counts stat } func (s *smartStatusOutput) Flush() { + if s.tableMode { + // Stop the action table tick outside of the lock to avoid lock ordering issues between s.done and + // s.lock, the goroutine in startActionTableTick can get blocked on the lock and be unable to read + // from the channel. + s.stopActionTableTick() + } + s.lock.Lock() defer s.lock.Unlock() @@ -180,8 +187,6 @@ func (s *smartStatusOutput) Flush() { s.runningActions = nil if s.tableMode { - s.stopActionTableTick() - // Update the table after clearing runningActions to clear it s.actionTable()