Sorry you ran into this issue. Unfortunately, this is pretty much how such features tend to be designed to keep overheads low. You make a good point that we should have more diagnostics to detect when this happens. We can add a `runtime/metrics` metric, or perhaps add extend the capabilities of an experimental debug mode I'm working on for cleanups and finalizers (https://go.dev/cl/634599). At the very least, I'll make note of this in https://go.dev/doc/gc-guide.
Note also that even though `runtime.AddCleanup` is documented as running cleanups concurrently, 1. In Go 1.24 we don't actually do that, so it won't help you to switch in the short term. I have a patch for Go 1.25 to do that properly. (https://go.dev/cl/650697) 2. Even once we can run cleanups concurrently, it's still hazardous to spend a long time in a cleanup. The Go 1.25 implementation will not run each cleanup in its own goroutine, as that is just too expensive and very hard to change. You can still exhaust the finite number of goroutines used to run cleanups. Java Cleaners have a similar limitation in that each Cleaner runs all its actions on a single thread. ("The execution of the cleaning action is performed by a thread associated with the cleaner. [...] The thread runs until all registered cleaning actions have completed and the cleaner itself is reclaimed by the garbage collector.", from https://docs.oracle.com/javase/9/docs/api/java/lang/ref/Cleaner.html) There is a difference here in that you can create as many cleaners as you want, AFAICT. I'll note that we might be able to do something more complicated in the future in which we "detach" a cleanup goroutine if we detect that it blocks or runs too long at runtime. But just to set expectations, I don't think there's a high likelihood that we'll do something like this any time soon. On Wednesday, March 19, 2025 at 8:49:59 AM UTC-4 Gavra wrote: > Yes, even if it was only a few ms, they should have run it in a goroutine. > > On Wednesday, 19 March 2025 at 14:17:56 UTC+2 Robert Engels wrote: > >> The docs: >> >> “ A single goroutine runs all finalizers for a program, sequentially. If >> a finalizer must run for a long time, it should do so by starting a new >> goroutine.” >> >> So the code did not follow the api docs - as apparently the close() is >> indefinite. >> >> On Mar 19, 2025, at 6:46 AM, Gavra <gav...@gmail.com> wrote: >> >> Yes, I intend to open a bug for them. >> >> I agree that one should not relay on the execution of finalizers. But, >> the fact that the runtime just piles them up because one package did wrong >> is outrageous. >> >> By the way, I am not sure why but I can see the mfinal routine only when >> running my program from Goland; When I build it manually the routine is >> invisible using pprof. >> >> On Wednesday, 19 March 2025 at 13:38:04 UTC+2 Robert Engels wrote: >> >>> In fact the code you reference - the close() - does things the Go docs >>> warn specifically not to do. >>> >>> You may be better off using runtime.AddCleanup() >>> >>> >>> >>> On Mar 19, 2025, at 6:32 AM, Robert Engels <ren...@ix.netcom.com> wrote: >>> >>> >>> >>> In principle, I would argue that there is a correctness problem. You >>> should not rely on finalizers ever - they are catches and often optional - >>> so the design relying on finalizers to run is what is broken. >>> >>> In the real world they can make solving certain problems much easier - >>> especially with shared resources. I know Java has deprecated them in lieu >>> of other technologies like Cleaners. >>> >>> >>> On Mar 19, 2025, at 6:19 AM, Gavra <gav...@gmail.com> wrote: >>> >>> >>> https://github.com/hirochachacha/go-smb2/blob/c8e61c7a5fa7bcd1143359f071f9425a9f4dda3f/client.go#L1063 >>> We are looking for why exactly it blocked (probably incorrect ctx) but I >>> think this close should run in a goroutine. >>> >>> On Wednesday, 19 March 2025 at 12:29:34 UTC+2 Brian Candler wrote: >>> >>>> On Wednesday, 19 March 2025 at 09:55:58 UTC Gavra wrote: >>>> >>>> This finalizer blocks the runtime's finalizer goroutine >>>> >>>> >>>> Out of interest, what made it block? Was the finalizer doing some >>>> channel communication, for example? >>>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to golang-nuts...@googlegroups.com. >>> To view this discussion visit >>> https://groups.google.com/d/msgid/golang-nuts/5c7c034d-3bc6-4fe5-82bb-a318310bd82fn%40googlegroups.com >>> >>> <https://groups.google.com/d/msgid/golang-nuts/5c7c034d-3bc6-4fe5-82bb-a318310bd82fn%40googlegroups.com?utm_medium=email&utm_source=footer> >>> . >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "golang-nuts" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to golang-nuts...@googlegroups.com. >>> >>> To view this discussion visit >>> https://groups.google.com/d/msgid/golang-nuts/6AABBB52-5BC6-4874-900B-C423E37952C4%40ix.netcom.com >>> >>> <https://groups.google.com/d/msgid/golang-nuts/6AABBB52-5BC6-4874-900B-C423E37952C4%40ix.netcom.com?utm_medium=email&utm_source=footer> >>> . >>> >>> -- >> You received this message because you are subscribed to the Google Groups >> "golang-nuts" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to golang-nuts...@googlegroups.com. >> >> To view this discussion visit >> https://groups.google.com/d/msgid/golang-nuts/75da8ea2-c099-483c-969a-ab99a91da2a4n%40googlegroups.com >> >> <https://groups.google.com/d/msgid/golang-nuts/75da8ea2-c099-483c-969a-ab99a91da2a4n%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> >> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/3031839f-655d-47b4-b6c4-2921edbaa79bn%40googlegroups.com.