From e7c30c78aeb2bf1ab602f2e789b86db8d9942388 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Thu, 25 May 2023 09:35:40 -0700 Subject: [PATCH] For Go 1.21+, ask the Go runtime about its GC. For background, see: https://go-review.googlesource.com/c/go/+/498121 and https://go-review.googlesource.com/c/go/+/498261 --- assume-no-moving-gc.go | 20 +++++++++----------- check.go | 36 ++++++++++++++++++++++++++++++++++++ untested.go | 26 -------------------------- 3 files changed, 45 insertions(+), 37 deletions(-) create mode 100644 check.go delete mode 100644 untested.go diff --git a/assume-no-moving-gc.go b/assume-no-moving-gc.go index 72b009a..60561d0 100644 --- a/assume-no-moving-gc.go +++ b/assume-no-moving-gc.go @@ -10,9 +10,10 @@ // analysis keeps on the stack. Ensuring things aren't stack-allocated // is the caller's responsibility. // -// This package is then updated for new Go versions when that -// is still the case and explodes at runtime with a failure -// otherwise, unless an environment variable overrides it. +// This package is then updated as needed for new Go versions when +// that is still the case and explodes at runtime with a failure +// otherwise, with the idea that it's better to not start at all than +// to silently corrupt your data at runtime. // // To use: // @@ -20,15 +21,12 @@ // // There is no API. // -// It is intentional that this package will break code that's not updated -// regularly to double check its assumptions about the world and new Go -// versions. If you play stupid games with unsafe pointers, the stupid prize -// is this maintenance cost. (The alternative would be memory corruption if -// some unmaintained, unsafe library were built with a future version of Go -// that worked very differently than when the unsafe library was built.) -// Ideally you shouldn't write unsafe code, though. +// As of Go 1.21, this package asks the Go runtime whether it can move +// heap objects around. If you get an error on versions prior to that, +// go get go4.org/unsafe/assume-no-moving-gc@latest and things will +// work. // // The GitHub repo is at https://github.com/go4org/unsafe-assume-no-moving-gc package assume_no_moving_gc -const env = "ASSUME_NO_MOVING_GC_UNSAFE_RISK_IT_WITH" +const env = "ASSUME_NO_MOVING_GC_UNSAFE" diff --git a/check.go b/check.go new file mode 100644 index 0000000..a2fbf46 --- /dev/null +++ b/check.go @@ -0,0 +1,36 @@ +// Copyright 2020 Brad Fitzpatrick. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build go1.21 +// +build go1.21 + +package assume_no_moving_gc + +import ( + "os" + _ "unsafe" +) + +//go:linkname heapObjectsCanMove runtime.heapObjectsCanMove +func heapObjectsCanMove() bool + +func init() { + if !heapObjectsCanMove() { + // The unsafe assumptions made by the package + // importing this package still hold. All's good. (at + // least unless they made other assumption this + // package doesn't concern itself with) + return + } + if os.Getenv(env) == "play-with-fire" { + return + } + panic(` +Something in this program imports go4.org/unsafe/assume-no-moving-gc to +declare that it assumes a non-moving garbage collector, but the version +of Go you're using declares that its heap objects can now move around. +This program is no longer safe. You should update your packages which import +go4.org/unsafe/assume-no-moving-gc. To risk it and bypass this check, set +ASSUME_NO_MOVING_GC_UNSAFE=play-with-fire and cross your fingers.`) +} diff --git a/untested.go b/untested.go deleted file mode 100644 index fd7dc15..0000000 --- a/untested.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2020 Brad Fitzpatrick. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build go1.21 -// +build go1.21 - -package assume_no_moving_gc - -import ( - "os" - "runtime" - "strings" -) - -func init() { - dots := strings.SplitN(runtime.Version(), ".", 3) - v := runtime.Version() - if len(dots) >= 2 { - v = dots[0] + "." + dots[1] - } - if os.Getenv(env) == v { - return - } - panic("Something in this program imports go4.org/unsafe/assume-no-moving-gc to declare that it assumes a non-moving garbage collector, but your version of go4.org/unsafe/assume-no-moving-gc hasn't been updated to assert that it's safe against the " + v + " runtime. You can try updating this package by running \"go get go4.org/unsafe/assume-no-moving-gc@latest\". If that doesn't work and you want to risk it, run with environment variable " + env + "=\"" + v + "\" set. Notably, if " + v + " adds a moving garbage collector, this program is unsafe to use.") -}