bc1dd00a846834b5cc58c141d5a40f3692e43254 — Chris Waldon 2 months ago 2b1cec7 main
list: [hotfix] drop runtime.SetFinalizer

This commit removes the use of runtime.SetFinalizer from list.Manager.
I added it in order to try to ensure that the goroutine it spawns was
always cleaned up, but I didn't realize that doing so would break the
garbage collector's ability to GC the manager if any of the manager's
hook functions managed to create an import cycle (this is very easy to
do, as it's natural to provide methods on a type containing the manager
as hooks).

https://pkg.go.dev/runtime#SetFinalizer says:

If a cyclic structure includes a block with a finalizer, that cycle is
not guaranteed to be garbage collected and the finalizer is not guaranteed
to run, because there is no ordering that respects the dependencies.

This means we can't safely automate the destruction of that goroutine,
and must rely upon users to properly invoke Shutdown().

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
1 files changed, 0 insertions(+), 7 deletions(-)

M list/manager.go
M list/manager.go => list/manager.go +0 -7
@@ 3,7 3,6 @@ package list
import (


@@ 156,12 155,6 @@ func NewManager(maxSize int, hooks Hooks) *Manager {

	rm.requests, rm.viewports, rm.stateUpdates = asyncProcess(maxSize, hooks)

	// Ensure that the asynchronous processing goroutine is shut down when
	// the manager is garbage collected.
	runtime.SetFinalizer(rm, func(m *Manager) {

	return rm