After https://golang.org/cl/45930043
lots of programs crash on darwin/386 with:
panic: runtime error: call of nil func value
[signal 0xa code=0x2 addr=0x0 pc=0x0]
The crash is easily reproducible with:
$ go test -run=TestParseGlob text/template
The culprit is:
func ReadDirent(fd int, buf []byte) (n int, err error) {
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
// TODO(rsc): Can we use a single global basep for all calls?
return Getdirentries(fd, buf, new(uintptr))
}
The compiler seems to think that new(uintptr) is not alive during syscall. And combines
it... with return address? And then syscall writes 0 to return address.
With the following fix 'go test std' passes:
+var xx **uintptr
+
func ReadDirent(fd int, buf []byte) (n int, err error) {
// Final argument is (basep *uintptr) and the syscall doesn't take nil.
// TODO(rsc): Can we use a single global basep for all calls?
- return Getdirentries(fd, buf, new(uintptr))
+ x := new(uintptr)
+ if *x != 0 {
+ xx = &x
+ }
+ return Getdirentries(fd, buf, x)
}
It seems wrong that compiler think that the var is not alive. And it probably could
break w/o the escape-related change, because liveness is orthogonal to escape-ness.
Russ, what do you think?
The text was updated successfully, but these errors were encountered:
This was fixed in CL https://golang.org/cl/53840043.
I don't believe you that the compiler thought new(uintptr) is not alive during the
system call. It was definitely alive, it was just passing a pointer to a stack value now
instead of a heap-allocated value. And on 32-bit systems uintptr is only 4 bytes but the
kernel wanted (and wrote) 8. It only worked before because if you asked the memory
allocator for 4 bytes you got at least 8 anyway.
The text was updated successfully, but these errors were encountered: