]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: keep objects alive while stopping cleanups
authorMichael Anthony Knyszek <mknyszek@google.com>
Wed, 12 Nov 2025 18:22:58 +0000 (18:22 +0000)
committerGopher Robot <gobot@golang.org>
Thu, 13 Nov 2025 00:14:30 +0000 (16:14 -0800)
There are two places in cmd/go where cleanups are stopped before they
fire, and where the objects the cleanups are attached to may be dead
while we call Stop. This is essentially a race between Stop and the
cleanup being called. This can be fine, but these cleanups are used as
a way to check some invariants, so just panic if they're executed. As a
result, if they fire erroneously, they'll take down the whole process,
even if no invariant was actually violated.

The runtime.Cleanup.Stop documentation explains that users of Stop need
to hold the object alive across the call to Stop if they want to be sure
that Stop succeeds, so do that here by adding an explicit
runtime.KeepAlive call.

Kudos to Michael Pratt for finding the issue.

Fixes #74780.

Change-Id: I22e6f4642ac68f727ca3781f5d39a85015047925
Reviewed-on: https://go-review.googlesource.com/c/go/+/719961
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
src/cmd/go/internal/base/limit.go
src/cmd/go/internal/lockedfile/lockedfile.go

index 4317432527a433f112314e19040898b49b2398b0..a90b700a031e3a1bc58dae943a31ca151ec5aced 100644 (file)
@@ -63,6 +63,12 @@ func AcquireNet() (release func(), err error) {
                        <-netLimitSem
                }
                cleanup.Stop()
+
+               // checker may be dead at the moment after we last access
+               // it in this function, so the cleanup can fire before Stop
+               // completes. Keep checker alive while we call Stop. See
+               // the documentation for runtime.Cleanup.Stop.
+               runtime.KeepAlive(checker)
        }, nil
 }
 
index 8bd2ffbe8f7860c1f5d49392fc9c0518a5b1feda..f48124ffbc0d3ea2a439ca3f18babf7c1c74f2d7 100644 (file)
@@ -94,6 +94,11 @@ func (f *File) Close() error {
 
        err := closeFile(f.osFile.File)
        f.cleanup.Stop()
+       // f may be dead at the moment after we access f.cleanup,
+       // so the cleanup can fire before Stop completes. Keep f
+       // alive while we call Stop. See the documentation for
+       // runtime.Cleanup.Stop.
+       runtime.KeepAlive(f)
        return err
 }