为什么在导入zmq4时,go v1.8在armv7上无法分配堆位图?

huangapple go评论117阅读模式
英文:

Why does go v1.8 fail to allocate heap bitmap on armv7 when importing zmq4?

问题

我正在使用go v1.8在一个armv7目标上,并且一切正常,直到我导入zeromq,然后甚至这个也不起作用:

  1. package main
  2. import (
  3. zmq "github.com/pebbe/zmq4"
  4. "fmt"
  5. )
  6. func main() {
  7. fmt.Println(zmq.Version())
  8. }

在目标上运行它会得到以下结果:

  1. ./zmq
  2. fatal error: runtime: out of memory
  3. runtime stack:
  4. runtime.throw(0xc8d3d, 0x16)
  5. /usr/lib/go/src/runtime/panic.go:596 +0x70 fp=0x7eb018a0 sp=0x7eb01894
  6. runtime.sysMap(0x6d752000, 0x74d4000, 0x1, 0x146b60)
  7. /usr/lib/go/src/runtime/mem_linux.go:227 +0xb0 fp=0x7eb018c4 sp=0x7eb018a0
  8. runtime.(*mheap).mapBits(0x139d58, 0x74d26000)
  9. /usr/lib/go/src/runtime/mbitmap.go:159 +0x94 fp=0x7eb018dc sp=0x7eb018c4
  10. runtime.(*mheap).sysAlloc(0x139d58, 0x100000, 0x30414)
  11. /usr/lib/go/src/runtime/malloc.go:428 +0x2dc fp=0x7eb0191c sp=0x7eb018dc
  12. runtime.(*mheap).grow(0x139d58, 0x8, 0x0)
  13. /usr/lib/go/src/runtime/mheap.go:774 +0xd0 fp=0x7eb0194c sp=0x7eb0191c
  14. runtime.(*mheap).allocSpanLocked(0x139d58, 0x1, 0x0)
  15. /usr/lib/go/src/runtime/mheap.go:678 +0x468 fp=0x7eb0196c sp=0x7eb0194c
  16. runtime.(*mheap).alloc_m(0x139d58, 0x1, 0x10, 0x0, 0x0)
  17. /usr/lib/go/src/runtime/mheap.go:562 +0xdc fp=0x7eb019a4 sp=0x7eb0196c
  18. runtime.(*mheap).alloc.func1()
  19. /usr/lib/go/src/runtime/mheap.go:627 +0x3c fp=0x7eb019c0 sp=0x7eb019a4
  20. runtime.systemstack(0x7eb019d4)
  21. /usr/lib/go/src/runtime/asm_arm.s:278 +0xa8 fp=0x7eb019c4 sp=0x7eb019c0
  22. runtime.(*mheap).alloc(0x139d58, 0x1, 0x10, 0x100, 0x1)
  23. /usr/lib/go/src/runtime/mheap.go:628 +0x60 fp=0x7eb019ec sp=0x7eb019c4
  24. runtime.(*mcentral).grow(0x13ab98, 0x0)
  25. /usr/lib/go/src/runtime/mcentral.go:212 +0x84 fp=0x7eb01a18 sp=0x7eb019ec
  26. runtime.(*mcentral).cacheSpan(0x13ab98, 0x146b68)
  27. /usr/lib/go/src/runtime/mcentral.go:93 +0x104 fp=0x7eb01a5c sp=0x7eb01a18
  28. runtime.(*mcache).refill(0x649e5000, 0x10, 0x146b68)
  29. /usr/lib/go/src/runtime/mcache.go:122 +0x7c fp=0x7eb01a70 sp=0x7eb01a5c
  30. runtime.(*mcache).nextFree.func1()
  31. /usr/lib/go/src/runtime/malloc.go:525 +0x24 fp=0x7eb01a80 sp=0x7eb01a70
  32. runtime.systemstack(0x7eb01aa4)
  33. /usr/lib/go/src/runtime/asm_arm.s:278 +0xa8 fp=0x7eb01a84 sp=0x7eb01a80
  34. runtime.(*mcache).nextFree(0x649e5000, 0x649e5010, 0x7eb01acc, 0x1ebd4, 0x21c40)
  35. /usr/lib/go/src/runtime/malloc.go:526 +0x9c fp=0x7eb01ab0 sp=0x7eb01a84
  36. runtime.mallocgc(0xf0, 0xc2548, 0x1, 0x64a26001)
  37. /usr/lib/go/src/runtime/malloc.go:678 +0x8c0 fp=0x7eb01b08 sp=0x7eb01ab0
  38. runtime.newobject(0xc2548, 0x1384a0)
  39. /usr/lib/go/src/runtime/malloc.go:807 +0x2c fp=0x7eb01b1c sp=0x7eb01b08
  40. runtime.malg(0x8000, 0x2710)
  41. /usr/lib/go/src/runtime/proc.go:2821 +0x1c fp=0x7eb01b38 sp=0x7eb01b1c
  42. runtime.mpreinit(0x138730)
  43. /usr/lib/go/src/runtime/os_linux.go:302 +0x1c fp=0x7eb01b44 sp=0x7eb01b38
  44. runtime.mcommoninit(0x138730)
  45. /usr/lib/go/src/runtime/proc.go:540 +0x94 fp=0x7eb01b5c sp=0x7eb01b44
  46. runtime.schedinit()
  47. /usr/lib/go/src/runtime/proc.go:476 +0x40 fp=0x7eb01b78 sp=0x7eb01b5c
  48. runtime.rt0_go(0x7eb01d14, 0x76ee4000, 0x7eb01d14, 0x1, 0x5cd10, 0x7eb01c58, 0x76f8e000, 0xcef6f281, 0xc6a63e08, 0x128, ...)
  49. /usr/lib/go/src/runtime/asm_arm.s:61 +0x84 fp=0x7eb01bb8 sp=0x7eb01b78

跟踪显示了有问题的mmap:

  1. mmap2(0x74c54000, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x74c54000
  2. mmap2(0x6d77e000, 122511360, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

第一个是正确的,那是块的大小,但第二个是它分配位图的地方。它可能应该小16倍。

我尝试过调试,但在GDB下它可以工作。也许GDB进行了一些虚拟化?

  1. gdbserver :1000 zmq
  2. Process zmq created; pid = 817
  3. Listening on port 1000
  4. Remote debugging from host 10.0.0.36
  5. 4 2 1
  6. Child exited with status 0

到目前为止,我测试过的所有纯Go程序也都能正常工作。

为什么导入zeromq会导致它失败?是go的arm端口中有bug吗?

英文:

I'm using go v1.8 on an armv7 target and everything works until I import zeromq, and then not even this works:

  1. package main
  2. import (
  3. zmq "github.com/pebbe/zmq4"
  4. "fmt"
  5. )
  6. func main() {
  7. fmt.Println(zmq.Version())
  8. }

Running it on the target gives the following:

  1. ./zmq
  2. fatal error: runtime: out of memory
  3. runtime stack:
  4. runtime.throw(0xc8d3d, 0x16)
  5. /usr/lib/go/src/runtime/panic.go:596 +0x70 fp=0x7eb018a0 sp=0x7eb01894
  6. runtime.sysMap(0x6d752000, 0x74d4000, 0x1, 0x146b60)
  7. /usr/lib/go/src/runtime/mem_linux.go:227 +0xb0 fp=0x7eb018c4 sp=0x7eb018a0
  8. runtime.(*mheap).mapBits(0x139d58, 0x74d26000)
  9. /usr/lib/go/src/runtime/mbitmap.go:159 +0x94 fp=0x7eb018dc sp=0x7eb018c4
  10. runtime.(*mheap).sysAlloc(0x139d58, 0x100000, 0x30414)
  11. /usr/lib/go/src/runtime/malloc.go:428 +0x2dc fp=0x7eb0191c sp=0x7eb018dc
  12. runtime.(*mheap).grow(0x139d58, 0x8, 0x0)
  13. /usr/lib/go/src/runtime/mheap.go:774 +0xd0 fp=0x7eb0194c sp=0x7eb0191c
  14. runtime.(*mheap).allocSpanLocked(0x139d58, 0x1, 0x0)
  15. /usr/lib/go/src/runtime/mheap.go:678 +0x468 fp=0x7eb0196c sp=0x7eb0194c
  16. runtime.(*mheap).alloc_m(0x139d58, 0x1, 0x10, 0x0, 0x0)
  17. /usr/lib/go/src/runtime/mheap.go:562 +0xdc fp=0x7eb019a4 sp=0x7eb0196c
  18. runtime.(*mheap).alloc.func1()
  19. /usr/lib/go/src/runtime/mheap.go:627 +0x3c fp=0x7eb019c0 sp=0x7eb019a4
  20. runtime.systemstack(0x7eb019d4)
  21. /usr/lib/go/src/runtime/asm_arm.s:278 +0xa8 fp=0x7eb019c4 sp=0x7eb019c0
  22. runtime.(*mheap).alloc(0x139d58, 0x1, 0x10, 0x100, 0x1)
  23. /usr/lib/go/src/runtime/mheap.go:628 +0x60 fp=0x7eb019ec sp=0x7eb019c4
  24. runtime.(*mcentral).grow(0x13ab98, 0x0)
  25. /usr/lib/go/src/runtime/mcentral.go:212 +0x84 fp=0x7eb01a18 sp=0x7eb019ec
  26. runtime.(*mcentral).cacheSpan(0x13ab98, 0x146b68)
  27. /usr/lib/go/src/runtime/mcentral.go:93 +0x104 fp=0x7eb01a5c sp=0x7eb01a18
  28. runtime.(*mcache).refill(0x649e5000, 0x10, 0x146b68)
  29. /usr/lib/go/src/runtime/mcache.go:122 +0x7c fp=0x7eb01a70 sp=0x7eb01a5c
  30. runtime.(*mcache).nextFree.func1()
  31. /usr/lib/go/src/runtime/malloc.go:525 +0x24 fp=0x7eb01a80 sp=0x7eb01a70
  32. runtime.systemstack(0x7eb01aa4)
  33. /usr/lib/go/src/runtime/asm_arm.s:278 +0xa8 fp=0x7eb01a84 sp=0x7eb01a80
  34. runtime.(*mcache).nextFree(0x649e5000, 0x649e5010, 0x7eb01acc, 0x1ebd4, 0x21c40)
  35. /usr/lib/go/src/runtime/malloc.go:526 +0x9c fp=0x7eb01ab0 sp=0x7eb01a84
  36. runtime.mallocgc(0xf0, 0xc2548, 0x1, 0x64a26001)
  37. /usr/lib/go/src/runtime/malloc.go:678 +0x8c0 fp=0x7eb01b08 sp=0x7eb01ab0
  38. runtime.newobject(0xc2548, 0x1384a0)
  39. /usr/lib/go/src/runtime/malloc.go:807 +0x2c fp=0x7eb01b1c sp=0x7eb01b08
  40. runtime.malg(0x8000, 0x2710)
  41. /usr/lib/go/src/runtime/proc.go:2821 +0x1c fp=0x7eb01b38 sp=0x7eb01b1c
  42. runtime.mpreinit(0x138730)
  43. /usr/lib/go/src/runtime/os_linux.go:302 +0x1c fp=0x7eb01b44 sp=0x7eb01b38
  44. runtime.mcommoninit(0x138730)
  45. /usr/lib/go/src/runtime/proc.go:540 +0x94 fp=0x7eb01b5c sp=0x7eb01b44
  46. runtime.schedinit()
  47. /usr/lib/go/src/runtime/proc.go:476 +0x40 fp=0x7eb01b78 sp=0x7eb01b5c
  48. runtime.rt0_go(0x7eb01d14, 0x76ee4000, 0x7eb01d14, 0x1, 0x5cd10, 0x7eb01c58, 0x76f8e000, 0xcef6f281, 0xc6a63e08, 0x128, ...)
  49. /usr/lib/go/src/runtime/asm_arm.s:61 +0x84 fp=0x7eb01bb8 sp=0x7eb01b78

Tracing shows the offending mmap:

  1. mmap2(0x74c54000, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x74c54000
  2. mmap2(0x6d77e000, 122511360, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)

The first one is right, that's the chunk size, but the second is where it allocates the bitmap. It should be probably 16x smaller.

I tried debugging but it works under GDB. Maybe GDB does some virtualization?

  1. gdbserver :1000 zmq
  2. Process zmq created; pid = 817
  3. Listening on port 1000
  4. Remote debugging from host 10.0.0.36
  5. 4 2 1
  6. Child exited with status 0

So far, all pure go programs I've tested work as well.

Why does importing zeromq cause it to fail? Is there a bug in the arm port of go?

答案1

得分: 1

通过 https://github.com/golang/go/commit/bb6309cd63b35a81a8527efaad58847a83039947 进行修复。

libzmq 必须包含一些全局构造函数,在 Go 运行时启动之前调整进程的内存映射。

英文:

Fixed by https://github.com/golang/go/commit/bb6309cd63b35a81a8527efaad58847a83039947

libzmq must contain some global constructors which adjust the process memory map before the go runtime starts.

huangapple
  • 本文由 发表于 2017年4月4日 04:29:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/43193685.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定