fix race condition index out of bound crash in gridview

This commit is contained in:
Drew Weymouth
2023-05-11 16:43:10 -07:00
parent 0a20299cf4
commit b2dce99714
+31 -21
View File
@@ -129,11 +129,11 @@ func (g *GridView) Clear() {
func (g *GridView) Reset(iter GridViewIterator) { func (g *GridView) Reset(iter GridViewIterator) {
g.itemsMutex.Lock() g.itemsMutex.Lock()
g.items = nil g.items = nil
g.itemsMutex.Unlock()
g.fetching = false g.fetching = false
g.done = false g.done = false
g.highestShown = 0 g.highestShown = 0
g.iter = iter g.iter = iter
g.itemsMutex.Unlock()
g.fetchMoreItems(36) g.fetchMoreItems(36)
} }
@@ -194,8 +194,13 @@ func (g *GridView) doUpdateItemCard(itemIdx int, card *GridViewItem) {
if itemIdx > g.highestShown { if itemIdx > g.highestShown {
g.highestShown = itemIdx g.highestShown = itemIdx
} }
var item GridViewItemModel
g.itemsMutex.RLock() g.itemsMutex.RLock()
item := g.items[itemIdx] // itemIdx can rarely be out of range if the data is being updated
// as the view is requested to refresh
if itemIdx < len(g.items) {
item = g.items[itemIdx]
}
g.itemsMutex.RUnlock() g.itemsMutex.RUnlock()
if card.PrevID == item.ID { if card.PrevID == item.ID {
// nothing to do // nothing to do
@@ -208,26 +213,31 @@ func (g *GridView) doUpdateItemCard(itemIdx int, card *GridViewItem) {
card.ImgLoadCancel() card.ImgLoadCancel()
card.ImgLoadCancel = nil card.ImgLoadCancel = nil
} }
if img, ok := g.imageFetcher.GetCoverThumbnailFromCache(item.CoverArtID); ok { if item.CoverArtID != "" {
card.Cover.SetImage(img) if img, ok := g.imageFetcher.GetCoverThumbnailFromCache(item.CoverArtID); ok {
} else { card.Cover.SetImage(img)
card.Cover.SetImageResource(res.ResAlbumplaceholderPng) } else {
// asynchronously fetch cover image card.Cover.SetImageResource(res.ResAlbumplaceholderPng)
ctx, cancel := context.WithCancel(context.Background()) // asynchronously fetch cover image
card.ImgLoadCancel = cancel ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) { card.ImgLoadCancel = cancel
i, err := g.imageFetcher.GetCoverThumbnail(item.CoverArtID) go func(ctx context.Context) {
select { i, err := g.imageFetcher.GetCoverThumbnail(item.CoverArtID)
case <-ctx.Done(): select {
return case <-ctx.Done():
default: return
if err == nil { default:
card.Cover.SetImage(i) if err == nil {
} else { card.Cover.SetImage(i)
log.Printf("error fetching image: %s", err.Error()) } else {
log.Printf("error fetching image: %s", err.Error())
}
} }
} }(ctx)
}(ctx) }
} else {
// use the placeholder image for an item that has no cover art ID
card.Cover.SetImageResource(res.ResAlbumplaceholderPng)
} }
// if user has scrolled near the bottom, fetch more // if user has scrolled near the bottom, fetch more