Skip to content
Open
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
16 changes: 13 additions & 3 deletions pkg/api/webassets/webassets.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net/http"
"os"
"path/filepath"
"sync"

"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/services/licensing"
Expand All @@ -31,12 +32,21 @@ type EntryPointInfo struct {
} `json:"assets,omitempty"`
}

var entryPointAssetsCache *dtos.EntryPointAssets = nil
var (
entryPointAssetsCacheMu sync.RWMutex // guard entryPointAssetsCache
entryPointAssetsCache *dtos.EntryPointAssets // TODO: get rid of global state
)

func GetWebAssets(ctx context.Context, cfg *setting.Cfg, license licensing.Licensing) (*dtos.EntryPointAssets, error) {
if cfg.Env != setting.Dev && entryPointAssetsCache != nil {
return entryPointAssetsCache, nil
entryPointAssetsCacheMu.RLock()
ret := entryPointAssetsCache
entryPointAssetsCacheMu.RUnlock()

if cfg.Env != setting.Dev && ret != nil {
return ret, nil
}
entryPointAssetsCacheMu.Lock()
defer entryPointAssetsCacheMu.Unlock()
Comment on lines +41 to +49
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix race condition in double-checked locking pattern.

The current implementation has a race condition between releasing the read lock (line 43) and acquiring the write lock (line 48). Multiple goroutines could unnecessarily recompute the cache.

Apply this diff to implement proper double-checked locking:

-	entryPointAssetsCacheMu.RLock()
-	ret := entryPointAssetsCache
-	entryPointAssetsCacheMu.RUnlock()
-
-	if cfg.Env != setting.Dev && ret != nil {
-		return ret, nil
-	}
-	entryPointAssetsCacheMu.Lock()
-	defer entryPointAssetsCacheMu.Unlock()
+	// Fast path: check cache with read lock
+	entryPointAssetsCacheMu.RLock()
+	if cfg.Env != setting.Dev && entryPointAssetsCache != nil {
+		ret := entryPointAssetsCache
+		entryPointAssetsCacheMu.RUnlock()
+		return ret, nil
+	}
+	entryPointAssetsCacheMu.RUnlock()
+
+	// Slow path: update cache with write lock
+	entryPointAssetsCacheMu.Lock()
+	defer entryPointAssetsCacheMu.Unlock()
+
+	// Double-check: another goroutine might have populated cache
+	if cfg.Env != setting.Dev && entryPointAssetsCache != nil {
+		return entryPointAssetsCache, nil
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
entryPointAssetsCacheMu.RLock()
ret := entryPointAssetsCache
entryPointAssetsCacheMu.RUnlock()
if cfg.Env != setting.Dev && ret != nil {
return ret, nil
}
entryPointAssetsCacheMu.Lock()
defer entryPointAssetsCacheMu.Unlock()
// Fast path: check cache with read lock
entryPointAssetsCacheMu.RLock()
if cfg.Env != setting.Dev && entryPointAssetsCache != nil {
ret := entryPointAssetsCache
entryPointAssetsCacheMu.RUnlock()
return ret, nil
}
entryPointAssetsCacheMu.RUnlock()
// Slow path: update cache with write lock
entryPointAssetsCacheMu.Lock()
defer entryPointAssetsCacheMu.Unlock()
// Double-check: another goroutine might have populated cache
if cfg.Env != setting.Dev && entryPointAssetsCache != nil {
return entryPointAssetsCache, nil
}
🤖 Prompt for AI Agents
In pkg/api/webassets/webassets.go around lines 41 to 49, the current
double-checked locking pattern releases the read lock before acquiring the write
lock, causing a race condition where multiple goroutines may recompute the
cache. To fix this, after acquiring the write lock, re-check if the cache is
still nil before recomputing it. This ensures only one goroutine updates the
cache while others use the cached value.


var err error
var result *dtos.EntryPointAssets
Expand Down
Loading