Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sync: Cond prevents struct from being GC'ed #50591

Closed
jpap opened this issue Jan 13, 2022 · 2 comments
Closed

sync: Cond prevents struct from being GC'ed #50591

jpap opened this issue Jan 13, 2022 · 2 comments

Comments

@jpap
Copy link
Contributor

jpap commented Jan 13, 2022

What version of Go are you using (go version)?

go1.17.6

Does this issue reproduce with the latest release?

Reproduces on https://go.dev/play/p/5bfwPnkYyY3

What operating system and processor architecture are you using (go env)?

Have tried on darwin/amd64, linux/mips32, and whatever os/arch runs on Go Playground.

What did you do?

  • Allocate a struct having a sync.Mutex and a *sync.Cond
  • Allocate the sync.Cond, using a pointer to the mutex in the struct.
  • Set a runtime finalizer on the struct, to see when it gets GC'ed
  • Drop references to struct, call runtime.GC(), sleep... no finalizer is called.
  • If you repeat the above, without initializing the sync.Cond or by setting x.cond = nil, the finalizer is called.

See the playgound for a sample: https://go.dev/play/p/5bfwPnkYyY3

I am currently using a workaround where I nilify the Cond in a struct when the associated struct is not pooled. I am using a custom pool, so I don't know if the above would be problematic for the GC when used with a sync.Pool that is purged.

What did you expect to see?

  • Struct should have been GC'ed

What did you see instead?

  • The opposite.
@randall77
Copy link
Contributor

From the spec of runtime.SetFinalizer:

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.

I think that's what you are running into. You have a 2-object cycle with a finalizer on one of the objects. That finalizer can never get run.

@jpap
Copy link
Contributor Author

jpap commented Jan 13, 2022

That's exactly it. Thank you, Keith.

@jpap jpap closed this as completed Jan 13, 2022
@golang golang locked and limited conversation to collaborators Jan 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants