faiface / pixel

A hand-crafted 2D game library in Go
MIT License
4.46k stars 246 forks source link

Build fails with fatal error: checkptr: pointer arithmetic computed bad pointer value #229

Closed fgrosse closed 3 years ago

fgrosse commented 4 years ago

I noticed Pixels current build on master fails on Travis with the following fatal error:

=== RUN   TestSprite_Draw

fatal error: checkptr: pointer arithmetic computed bad pointer value

goroutine 1 [running, locked to thread]:

runtime.throw(0x83649c, 0x37)
    /home/travis/.gimme/versions/go/src/runtime/panic.go:1116 +0x72 fp=0xc0000fbab0 sp=0xc0000fba80 pc=0x469f92
runtime.checkptrArithmetic(0x8, 0x0, 0x0, 0x0)
    /home/travis/.gimme/versions/go/src/runtime/checkptr.go:26 +0xd7 fp=0xc0000fbae0 sp=0xc0000fbab0 pc=0x43a6b7
github.com/go-gl/gl/v3.3-core/gl.PtrOffset(...)
    /home/travis/gopath/pkg/mod/github.com/go-gl/gl@v0.0.0-20190320180904-bf2b1f2f34d7/v3.3-core/gl/conversions.go:55
github.com/faiface/glhf.newVertexArray(0xc000186180, 0x6, 0x0)
    /home/travis/gopath/pkg/mod/github.com/faiface/glhf@v0.0.0-20181018222622-82a6317ac380/vertex.go:236 +0x865 fp=0xc0000fbc80 sp=0xc0000fbae0 pc=0x71ee85
github.com/faiface/glhf.MakeVertexSlice(...)
    /home/travis/gopath/pkg/mod/github.com/faiface/glhf@v0.0.0-20181018222622-82a6317ac380/vertex.go:36
github.com/faiface/pixel/pixelgl.NewGLTriangles.func1()
    /home/travis/gopath/src/github.com/faiface/pixel/pixelgl/gltriangles.go:34 +0x77 fp=0xc0000fbce0 sp=0xc0000fbc80 pc=0x734ab7
github.com/faiface/mainthread.Call.func1()
    /home/travis/gopath/pkg/mod/github.com/faiface/mainthread@v0.0.0-20171120011319-8b78f0a41ae3/mainthread.go:63 +0x47 fp=0xc0000fbd18 sp=0xc0000fbce0 pc=0x6e0287
github.com/faiface/mainthread.Run(0xc000090e00)
    /home/travis/gopath/pkg/mod/github.com/faiface/mainthread@v0.0.0-20171120011319-8b78f0a41ae3/mainthread.go:44 +0xfd fp=0xc0000fbdc0 sp=0xc0000fbd18 pc=0x6dfc1d
github.com/faiface/pixel/pixelgl.Run(0xc000090e00)
    /home/travis/gopath/src/github.com/faiface/pixel/pixelgl/run.go:32 +0x88 fp=0xc0000fbe60 sp=0xc0000fbdc0 pc=0x732048
github.com/faiface/pixel_test.TestMain(0xc000108000)
    /home/travis/gopath/src/github.com/faiface/pixel/pixel_test.go:42 +0x93 fp=0xc0000fbe90 sp=0xc0000fbe60 pc=0x7447f3
main.main()
    _testmain.go:133 +0x272 fp=0xc0000fbf88 sp=0xc0000fbe90 pc=0x75b072
runtime.main()
    /home/travis/.gimme/versions/go/src/runtime/proc.go:204 +0x223 fp=0xc0000fbfe0 sp=0xc0000fbf88 pc=0x46c743
runtime.goexit()
    /home/travis/.gimme/versions/go/src/runtime/asm_amd64.s:1374 +0x1 fp=0xc0000fbfe8 sp=0xc0000fbfe0 pc=0x4a23c1

goroutine 19 [chan receive]:

testing.(*T).Run(0xc000180000, 0x824de4, 0xf, 0x83d308, 0x1)
    /home/travis/.gimme/versions/go/src/testing/testing.go:1087 +0x70f
testing.runTests.func1(0xc000180000)
    /home/travis/.gimme/versions/go/src/testing/testing.go:1355 +0xa7
testing.tRunner(0xc000180000, 0xc000053d68)
    /home/travis/.gimme/versions/go/src/testing/testing.go:1035 +0x1f2
testing.runTests(0xc00000e040, 0xbf8c80, 0x1e, 0x1e, 0xbfa395e74e84a61c, 0x8bb4119a01, 0xc33080, 0x0)
    /home/travis/.gimme/versions/go/src/testing/testing.go:1353 +0x5a5
testing.(*M).Run(0xc000108000, 0x0)
    /home/travis/.gimme/versions/go/src/testing/testing.go:1263 +0x3b4
github.com/faiface/pixel_test.TestMain.func1()
    /home/travis/gopath/src/github.com/faiface/pixel/pixel_test.go:43 +0x45
github.com/faiface/mainthread.Run.func1(0xc000090e00, 0xc000080240)
    /home/travis/gopath/pkg/mod/github.com/faiface/mainthread@v0.0.0-20171120011319-8b78f0a41ae3/mainthread.go:37 +0x35
created by github.com/faiface/mainthread.Run
    /home/travis/gopath/pkg/mod/github.com/faiface/mainthread@v0.0.0-20171120011319-8b78f0a41ae3/mainthread.go:36 +0xf1

goroutine 241 [chan receive]:

github.com/faiface/mainthread.Call(0xc000139050)
    /home/travis/gopath/pkg/mod/github.com/faiface/mainthread@v0.0.0-20171120011319-8b78f0a41ae3/mainthread.go:66 +0x145
github.com/faiface/pixel/pixelgl.NewGLTriangles(0xc000186180, 0x8832c0, 0xc00000f480, 0xc0000f9b70)
    /home/travis/gopath/src/github.com/faiface/pixel/pixelgl/gltriangles.go:32 +0x131
github.com/faiface/pixel/pixelgl.(*Canvas).MakeTriangles(...)
    /home/travis/gopath/src/github.com/faiface/pixel/pixelgl/canvas.go:65
github.com/faiface/pixel/pixelgl.(*Window).MakeTriangles(0xc000242000, 0x8832c0, 0xc00000f480, 0xc0002883c8, 0x20)
    /home/travis/gopath/src/github.com/faiface/pixel/pixelgl/window.go:400 +0xa5
github.com/faiface/pixel.(*Drawer).Draw(0xc0001840d8, 0x880840, 0xc000242000)
    /home/travis/gopath/src/github.com/faiface/pixel/drawer.go:74 +0x4c6
github.com/faiface/pixel.(*Sprite).DrawColorMask(0xc0001840b0, 0x880840, 0xc000242000, 0x3ff0000000000000, 0x0, 0x0, 0x3ff0000000000000, 0x0, 0x0, 0x0, ...)
    /home/travis/gopath/src/github.com/faiface/pixel/sprite.go:87 +0x21d
github.com/faiface/pixel.(*Sprite).Draw(...)
    /home/travis/gopath/src/github.com/faiface/pixel/sprite.go:61
github.com/faiface/pixel_test.TestSprite_Draw(0xc00020bb80)
    /home/travis/gopath/src/github.com/faiface/pixel/pixel_test.go:66 +0x4a5
testing.tRunner(0xc00020bb80, 0x83d308)
    /home/travis/.gimme/versions/go/src/testing/testing.go:1035 +0x1f2
created by testing.(*T).Run
    /home/travis/.gimme/versions/go/src/testing/testing.go:1086 +0x6d7

FAIL    github.com/faiface/pixel    0.370s
fgrosse commented 4 years ago

I was able to reproduce the issue on my local machine as well:

$ git rev-parse HEAD
3be4e4cb84c9a33d2ff249a3c587dfb36dfebcd0

$ go version   
go version go1.14.2 linux/amd64

$ go test -race     
fatal error: checkptr: unsafe pointer arithmetic
…

Update: I can reproduce this with each invocation of go test. Does not look like a flaky test but a deterministic failure.

fgrosse commented 4 years ago

Looking at the stacktrace, the issue comes from:

/home/travis/gopath/pkg/mod/github.com/go-gl/gl@v0.0.0-20190320180904-bf2b1f2f34d7/v3.3-core/gl/conversions.go:55

This is the function at the vendored revision:

// PtrOffset takes a pointer offset and returns a GL-compatible pointer.
// Useful for functions such as glVertexAttribPointer that take pointer
// parameters indicating an offset rather than an absolute memory address.
func PtrOffset(offset int) unsafe.Pointer {
    return unsafe.Pointer(uintptr(offset))
}

Apparently this panics in the runtime with the checkptr: pointer arithmetic computed bad pointer value error (via go/src/runtime/checkptr.go:26).

I wonder why Pixel imports v3.3-core/gl already. I thought the GLFW update is still pending in #211?

Apparently github.com/go-gl/gl/v3.3-core is transitively used already via the currently used version of github.com/faiface/glhf?

On the other hand, I ran the same test with zergon321/add-glfw-v33 and get the same issue.

fgrosse commented 4 years ago

Running this without the race detector does not panic. Could be that the check is only enabled with the race detector or could be the defect is caused by a race condition?

delp commented 4 years ago

Hmm that seems strange. When I checked the Travis output, it said this command: go test -v -race -mod=readonly ./... exits with 1.

Running it locally, i found it passes when outside gopath and fails when inside gopath:

go test -v -race -mod=readonly ./...                                                                                                                                                                         
build flag -mod=readonly only valid when using modules
delp commented 4 years ago

running go test -race in my environment passes right now

$ go version   
go version go1.12.5 linux/amd64
fgrosse commented 4 years ago

I think you do not see the checkptr issue because that is a new feature of Go 1.14

This release adds -d=checkptr as a compile-time option for adding instrumentation to check that Go code is following unsafe.Pointer safety rules dynamically. This option is enabled by default (except on Windows) with the -race or -msan flags, […]

https://golang.org/doc/go1.14#compiler


Running it locally, i found it passes when outside gopath and fails when inside gopath:

I believe that you are describing an unrelated issue. You should not to use modules inside the Go path.

fgrosse commented 4 years ago

The documentation I linked above also gives some more description of the check that currently fails:

Specifically, -d=checkptr checks the following:

  1. When converting unsafe.Pointer to *T, the resulting pointer must be aligned appropriately for T.
  2. If the result of pointer arithmetic points into a Go heap object, one of the unsafe.Pointer-typed operands must point into the same object.

I haven't worked with unsafe yet but maybe somebody knows what it means that a pointer must be "aligned appropriately" :shrug:

fgrosse commented 4 years ago

Here the link to a fix of this problem in another Go program: https://github.com/pingcap/tidb/pull/14972

delp commented 4 years ago

I should take a look at this tonight, good learning opportunity.