Skip to content

Using testing/synctest on cache with janitor goroutine will hang forever #185

@cyrilc-pro

Description

@cyrilc-pro

When using the new experimental synctest feature of Go 1.24, I observe the following.

This test runs just fine:

func TestCacheWithoutJanitor(t *testing.T) {
	synctest.Run(func() {
		c := cache.New(time.Second, cache.NoExpiration)
		c.Set("foo", "bar", cache.DefaultExpiration)
	})
}

This test hangs forever:

func TestCacheWithJanitor(t *testing.T) {
	synctest.Run(func() {
		c := cache.New(time.Second, time.Minute)
		c.Set("foo", "bar", cache.DefaultExpiration)
	})
}

The incompatibility comes from:

  • synctest.Run will wait for all goroutines to exit (including the janitor goroutine)
  • cache uses runtime.SetFinalizer to stop the janitor goroutine but is never called

Forcing the GC to run produces a panic send on synctest channel from outside bubble:

func TestCacheWithJanitor(t *testing.T) {
	synctest.Run(func() {
		c := cache.New(time.Second, time.Minute)
		c.Set("foo", "bar", cache.DefaultExpiration)
		c = nil
		runtime.GC()
	})
}

My suggestion would be to provide a Close() function on the cache object to stop the janitor goroutine without the need for the GC to run.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions