Fix deadlock in ttyWriter.Done()

Resolves race condition between main thread calling Done() and UI thread
calling printWithDimensions(). The issue was that Done() held the mutex
while sending to the done channel, but the UI thread needed the same
mutex to process the done signal.

Fixed by sending the done signal before acquiring the mutex, allowing
the UI thread to receive the signal and release any held locks.

Fixes #13639

Signed-off-by: maks2134 <maks210306@yandex.by>
This commit is contained in:
maks2134 2026-03-17 00:16:00 +03:00 committed by Nicolas De loof
parent e8c2143498
commit 25b29d776b
8 changed files with 70 additions and 1 deletions

8
.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

9
.idea/compose.iml generated Normal file
View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

7
.idea/golinter.xml generated Normal file
View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GoLinterSettings">
<option name="customConfigFile" value="$PROJECT_DIR$/.golangci.yml" />
<option name="useCustomConfigFile" value="true" />
</component>
</project>

10
.idea/material_theme_project_new.xml generated Normal file
View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MaterialThemeProjectNewConfig">
<option name="metadata">
<MTProjectMetadataState>
<option name="userId" value="-7a070d14:19cf87c5499:-7ff2" />
</MTProjectMetadataState>
</option>
</component>
</project>

8
.idea/modules.xml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/compose.iml" filepath="$PROJECT_DIR$/.idea/compose.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View file

@ -176,13 +176,13 @@ func (w *ttyWriter) Start(ctx context.Context, operation string) {
func (w *ttyWriter) Done(operation string, success bool) {
w.print()
w.done <- true
w.mtx.Lock()
defer w.mtx.Unlock()
if w.ticker != nil {
w.ticker.Stop()
}
w.operation = ""
w.done <- true
}
func (w *ttyWriter) On(events ...api.Resource) {

View file

@ -18,6 +18,7 @@ package display
import (
"bytes"
"context"
"strings"
"sync"
"testing"
@ -422,3 +423,23 @@ func TestLenAnsi(t *testing.T) {
})
}
}
func TestDoneDeadlockFix(t *testing.T) {
w, _ := newTestWriter()
addTask(w, "test-task", "Working", "details", api.Working)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
w.Start(ctx, "test")
done := make(chan bool)
go func() {
w.Done("test", true)
done <- true
}()
select {
case <-done:
case <-time.After(5 * time.Second):
t.Fatal("Deadlock detected: Done() did not complete within 5 seconds")
}
}