Comments (5)
It looks like of the 16 test objects, the 15th one is somehow still reachable even though it shouldn't be.
It is possible that this test is flaky because of conservative scanning of top stack frames. A value on a random stack frame somewhere (probably a dead pointer) that happens to point to the object in question would keep it alive longer than this test expects.
Not sure why it is the 15th object in both cases. Maybe the last mallocgc
leaves that pointer somewhere deep on the stack and the subsequent call to gctestIsReachable
"adopts" that slot uninitialized in its frame, which then gets scanned. I'm not sure how that failure mode wouldn't be deterministic, though.
In any case, I think this test is kind of fundamentally unsound when conservative scanning exists. Not sure what to do about it.
@aclements who wrote the test, @mknyszek who is deep in this kind of stuff.
from go.
Found new dashboard test flakes for:
#!watchflakes
default <- pkg == "runtime" && test == "TestGCTestIsReachable"
2024-05-06 11:46 android-amd64-emu go@ff0bc466 runtime.TestGCTestIsReachable (log)
--- FAIL: TestGCTestIsReachable (0.03s)
gc_test.go:282: did not get expected reachable set; want 101010101010101, got 1101010101010101
from go.
Here's a test that demonstrates the "problem", that GCTestIsReachable
can report false positives based on dead pointers in stacks of other conservatively scanned goroutines.
//go:noinline
func writeToStack(p unsafe.Pointer) unsafe.Pointer {
var x [100]unsafe.Pointer
for i := range x {
x[i] = p
}
return x[7]
}
//go:noinline
func conservativelyScanned(c chan bool) int {
// Tell parent that the vulnerable frame is running.
c <- true
// Run in a state where GC has to interrupt us to proceed, and thus
// has to scan us conservatively.
var s int
for i := 0; i < 1<<30; i++ {
s += i * i
}
// Tell parent we're done.
c <- true
// Allocate a stack frame region that is uninitialized until here.
// This region overlaps writeToStack.x and thus contains dead copies
// of the pointer in question during the loop above.
var x [100]int
return x[s%len(x)]
}
func TestBadReachable(t *testing.T) {
s := make([]unsafe.Pointer, 1)
s[0] = unsafe.Pointer(new(*int))
c := make(chan bool, 1)
go func(p unsafe.Pointer) {
writeToStack(p)
conservativelyScanned(c)
}(s[0])
// Make sure child goroutine is in a state where conservative scanning would find s[0].
<-c
got := runtime.GCTestIsReachable(s...)
if got != 0 {
t.Fatalf("s[0] is reachable, but shouldn't be")
}
// Wait for goroutine to finish
<-c
}
(Add this to runtime/gc_test.go
.)
from go.
Wow, nice reproducer. Maybe we run the test as a testprog (or have the test binary reinvoke itself) and explicitly disable asynchronous preemption via GODEBUG
?
from go.
Yes, a reinvoke might work.
I do worry that if we enshrine GODEBUG=asyncpreemptoff=1
in order to make this test work, then we can never get rid of that debug option. Maybe that's not the end of the world.
from go.
Related Issues (20)
- import/path: issue title
- Bug Report: JSON Deserialization Case Sensitivity Issue in Go HOT 2
- proposal: runtime: add option to specify seed for `globalRand` HOT 1
- build: make.bash failures HOT 2
- x/net/http2: TestServer_MaxQueuedControlFrames failures HOT 2
- x/net/http2: TestServerWritesTrailers_WithoutFlush failures HOT 2
- proposal: iter: relax Pull to not panic because of thread locking state HOT 3
- os: RemoveAll susceptible to symlink race [1.21 backport] HOT 2
- os: RemoveAll susceptible to symlink race [1.22 backport] HOT 2
- net/http: Readdir method of DotFileHiding example does not conform to the doc
- cmd/cgo/internal/swig,cmd/go,x/build: swig cgo tests incompatible with C++ toolchain on builders HOT 5
- cmd/cgo: detect incompatible C declarations HOT 1
- x/telemetry: do not always fork cmd/go child HOT 1
- testing: "panic: Log in goroutine after Test..." is unreliable due to lack of synchronization on t.done
- x/tools/go/packages: Load(&cfg...) modifies cfg, contra explicit documentation
- x/telemetry: merge `sidecar.log` and the uploader's debug log
- testing: timeout failure text attributed to irrelevant, passing test
- net/http: switch default HTTP/2 write scheduler to round robin [freeze exception]
- cmd/cgo: _Cfunc_CString redeclared in this block HOT 4
- time: AfterFunc doesn't inherit parent goroutine labels
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go.