muesli / cache2go

Concurrency-safe Go caching library with expiration capabilities and access counters
Other
2.11k stars 518 forks source link

[bug]: delete operation in Foreach causes a deadlock #43

Open RealLiuSha opened 4 years ago

RealLiuSha commented 4 years ago

test code:

package main

import (
    "fmt"
    "time"

    "github.com/muesli/cache2go"
)

func main() {
    store := cache2go.Cache("test")
    store.AddAboutToDeleteItemCallback(func(v *cache2go.CacheItem) {
        fmt.Println("delete:", v)
    })

    key := "test1"
    store.Add(key, time.Second*1800, "asdfasdfasd")
    fmt.Println("fitst delete:")
    store.Delete(key)

    store.Add(key, time.Second*1800, "asdfasdfasd")

    go func() {
        time.Sleep(time.Second * 2)
        fmt.Println("goroutine delete:")

        store.Foreach(func(key interface{}, v *cache2go.CacheItem) {
            fmt.Println("start")
            store.Delete(key)
            fmt.Println("end")
        })
    }()

    time.Sleep(time.Second * 10)
}

Foreach polls for all, while Rlock is released only after the Foreach execution completes, resulting in a deadlock when deleted in Foreach

pythonsite commented 4 years ago

This error should be said that the user's use is not correct or the package design flaw itself?

leezhu commented 4 years ago

test code:

package main

import (
  "fmt"
  "time"

  "github.com/muesli/cache2go"
)

func main() {
  store := cache2go.Cache("test")
  store.AddAboutToDeleteItemCallback(func(v *cache2go.CacheItem) {
      fmt.Println("delete:", v)
  })

  key := "test1"
  store.Add(key, time.Second*1800, "asdfasdfasd")
  fmt.Println("fitst delete:")
  store.Delete(key)

  store.Add(key, time.Second*1800, "asdfasdfasd")

  go func() {
      time.Sleep(time.Second * 2)
      fmt.Println("goroutine delete:")

      store.Foreach(func(key interface{}, v *cache2go.CacheItem) {
          fmt.Println("start")
          store.Delete(key)
          fmt.Println("end")
      })
  }()

  time.Sleep(time.Second * 10)
}

Foreach polls for all, while Rlock is released only after the Foreach execution completes, resulting in a deadlock when deleted in Foreach

Yes,I try it and get a deadlock,trans func may not use Lock or RLock

lakshanwd commented 3 years ago

merge PR #48