karlseguin / ccache

A golang LRU Cache for high concurrency
MIT License
1.29k stars 120 forks source link

Bug report: TrackingGet goroutine unsafe with onDelete func #65

Open chenqiuhao1997 opened 3 years ago

chenqiuhao1997 commented 3 years ago

When Running TrackingGet, func gc could insert like this:

// Used when the cache was created with the Track() configuration option.
// Avoid otherwise
func (c *Cache) TrackingGet(key string) TrackedItem {
    item := c.Get(key)
    if item == nil {
        return NilTracked
    }

// switch to gc goroutine
...
        if c.tracking == false || atomic.LoadInt32(&item.refCount) == 0 {
            c.bucket(item.key).delete(item.key)
            c.size -= item.size
            c.list.Remove(element)
            if c.onDelete != nil {
                c.onDelete(item)
            }
            dropped += 1
            item.promotions = -2
        }
...
// switch back

    item.track()
    return item
}

That would cause getting items which have been processed onDelete func.

karlseguin commented 3 years ago

I'm not sure I understand the problem. TrackingGet and onDelete will get the same item, but tonDelete could be called at any point that 1 (or many) copies of item are out in user-code.

Sure, the refcount of item will be brought back up to 1, but I don't see that as being 'unsafe'.

Maybe I'm misunderstanding?