Просмотр исходного кода

Merge branch 'next' of github.com:OliveTin/OliveTin into next

jamesread 1 день назад
Родитель
Сommit
e6055f3de4
2 измененных файлов с 48 добавлено и 0 удалено
  1. 4 0
      service/internal/api/dashboards.go
  2. 44 0
      service/internal/api/dashboards_race_test.go

+ 4 - 0
service/internal/api/dashboards.go

@@ -148,6 +148,8 @@ func buildDefaultDashboard(rr *DashboardRenderRequest) *apiv1.Dashboard {
 		Contents: make([]*apiv1.DashboardComponent, 0),
 	}
 
+	rr.ex.MapActionBindingsLock.RLock()
+
 	for _, binding := range rr.ex.MapActionBindings {
 		if !defaultBindingEligibleForDashboard(rr, binding) {
 			continue
@@ -158,6 +160,8 @@ func buildDefaultDashboard(rr *DashboardRenderRequest) *apiv1.Dashboard {
 		}
 	}
 
+	rr.ex.MapActionBindingsLock.RUnlock()
+
 	if len(fieldset.Contents) > 0 {
 		fieldset.Contents = sortDashboardComponents(fieldset.Contents)
 		db.Contents = append(db.Contents, fieldset)

+ 44 - 0
service/internal/api/dashboards_race_test.go

@@ -0,0 +1,44 @@
+package api
+
+import (
+	"sync"
+	"testing"
+
+	"github.com/OliveTin/OliveTin/internal/executor"
+)
+
+// TestBuildDefaultDashboardConcurrentWithRebuild guards against a crash when the
+// default dashboard is built (e.g. by Init) while a config or entity reload
+// rebuilds the action map. Without the read lock in buildDefaultDashboard, the
+// Go runtime aborts with "concurrent map iteration and map write"; run with
+// -race to see the data race directly.
+func TestBuildDefaultDashboardConcurrentWithRebuild(t *testing.T) {
+	cfg, _, adminUser := buildViewPermissionTestConfig(t)
+	ex := executor.DefaultExecutor(cfg)
+	ex.RebuildActionMap()
+
+	rr := &DashboardRenderRequest{
+		AuthenticatedUser: adminUser,
+		cfg:               cfg,
+		ex:                ex,
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(2)
+
+	go func() {
+		defer wg.Done()
+		for i := 0; i < 200; i++ {
+			ex.RebuildActionMap()
+		}
+	}()
+
+	go func() {
+		defer wg.Done()
+		for i := 0; i < 200; i++ {
+			buildDefaultDashboard(rr)
+		}
+	}()
+
+	wg.Wait()
+}