-
Notifications
You must be signed in to change notification settings - Fork 17.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
runtime: writebarrierptr panic in isolated code snippet on Go 1.8.3 #21897
Comments
This is expected behavior. |
OK, thanks for taking a look. |
For valid uses of |
The original crash we're investigating was on macOS, and involved
But why is the Go GC treating |
Or, I believe, this is equivalent: /*
typedef const void *fooPtr;
*/
import "C"
import (
"fmt"
"time"
)
func main() {
x := C.fooPtr(uintptr(0x27))
for i := 0; i < 1000000; i++ {
fmt.Printf("%p\n", x)
time.Sleep(1)
}
} This comes up because some functions in the CoreFoundation library seems to be OK with these obviously non-pointer pointers, for instance CFGetTypeID. |
Slightly more digging, as I'm picking up a library that someone else wrote to solve this crasher, so a lot of this is new to me. As far as CoreFoundation is concerned, Also of note, we found this pointer in an array with other valid pointers. That's the contract of the CoreFoundation library call we are using. Also of note, we're never dereferencing this pointer, we're just copying it around and assigning it to other values, or printing it via |
Yeah, it looks like Apple decided to pack non-pointer things into a pointer.
Prints
It looks like a CFNumberRef isn't always a real pointer. If the integer is at most 56 bits, it is encoded directly in the pointer and the low bits (?) determine the encoding. This is unfortunate. I'm not sure what we can do about it. It bleeds up to CFTypeRef, the void* of the apple world. Maybe we teach cgo that it should use uintptr for all these CF*Ref types? We can't reasonably allocate them on the Go side, so that might work. If cgo could reliably detect them... It isn't just the pointer-to-the-zero-page problem noted earlier. We could manufacture a pointer to just about anywhere the runtime considers invalid (goroutine stacks, padding at the end of spans) using CFNumberCreate and just the right (or wrong, depending on your perspective) integer. Reopening. I'm not sure we can fix this, but we should probably consider if there's anything sensible to do. |
Does that mean it's currently impossible to call e.g. |
Casting to uintptr immediately should suffice. |
OpenGL has a similar issue in glFenceSync, which returns a GLsync, which is an opaque struct pointer type ( |
@dominikh, you mention in go-gl/gl#71 (comment) that doing e.g. Isn't that pretty bad? In this context, I can call functions that return a Does that mean I need to write C shims to take |
That is the conclusion I have reached, yes. I'd love to be proven wrong, though. |
@randall77 @ianlancetaylor can either of you guys comment on whether casting a non-pointer value to |
@akalin-keybase That is unsafe at the moment.
The first we might be able to fix with the right sprinkling of nosplit directives in cgo generated code. Neither can happen on returns, so there immediately casting to uintptr is ok. The only workaround I can see at the moment is to do the cast on the C side and pass uintptr across the c/go boundary. |
@akalin-keybase Go is not C, and Go has a simple rule: a variable of pointer type must hold a pointer value. Tricks like converting an integer to a pointer type, while valid in C, are not valid in Go. |
Change https://golang.org/cl/66332 mentions this issue: |
Note that even in C, “the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation”, and in general, “[i]f the So this isn't a portable idiom in C, either: it's only valid if you make non-standard assumptions about the C implementation. |
Thank you very much for this! |
Change https://golang.org/cl/81876 mentions this issue: |
The jobject type is declared as a pointer, but some JVMs (Dalvik, ART) store non-pointer values in them. In Go, we must use uintptr instead of a real pointer for these types. This is similar to the CoreFoundation types on Darwin which were "fixed" in CL 66332. Update #22906 Update #21897 RELNOTE=yes Change-Id: I0d4c664501d89a696c2fb037c995503caabf8911 Reviewed-on: https://go-review.googlesource.com/81876 Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
Change https://golang.org/cl/82917 mentions this issue: |
Update #22906 Update #21897 Change-Id: I73709b2fdac6981d4bc2f7dab0767f2dd7be3be5 Reviewed-on: https://go-review.googlesource.com/82917 Reviewed-by: Brad Fitzpatrick <[email protected]>
What version of Go are you using (
go version
)?1.8.3.
Does this issue reproduce with the latest release?
The issue does not repro with 1.9
What operating system and processor architecture are you using (
go env
)?Repro'ed on macOS and linux.
What did you do?
What did you expect to see?
No crash
What did you see instead?
The text was updated successfully, but these errors were encountered: