64Bit alignment issue on ARM7 (Raspberry Pi)

Hi,

I tried to compile the latest code of filebeat on my Raspbarry Pi 3 (Arch ARM Linux, armv7h). The compilation was successful, however during runtime it crashed as follows

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x4 pc=0xaaf58]

goroutine 25 [running]:
panic(0x4f8a08, 0x10b22008)
/usr/lib/go/src/runtime/panic.go:500 +0x33c
sync/atomic.addUint64(0x10d501cc, 0x1, 0x0, 0x1, 0x0)
/usr/lib/go/src/sync/atomic/64bit_arm.go:31 +0x68
github.com/elastic/beats/filebeat/prospector.(*Prospector).startHarvester(0x10d50140, 0x10d26c60, 0x23, 0x0, 0x0, 0x0, 0x751cd8, 0x10d23170, 0x169c6, 0x0, ...)
/home/kofi/beats/src/github.com/elastic/beats/filebeat/prospector/prospector.go:239 +0x30c
github.com/elastic/beats/filebeat/prospector.(*ProspectorLog).scan(0x10bca0f0)
/home/kofi/beats/src/github.com/elastic/beats/filebeat/prospector/prospector_log.go:232 +0x3f4
github.com/elastic/beats/filebeat/prospector.(*ProspectorLog).Run(0x10bca0f0)
/home/kofi/beats/src/github.com/elastic/beats/filebeat/prospector/prospector_log.go:77 +0xd8
github.com/elastic/beats/filebeat/prospector.(*Prospector).Run(0x10d50140, 0x0)
/home/kofi/beats/src/github.com/elastic/beats/filebeat/prospector/prospector.go:156 +0x338
github.com/elastic/beats/filebeat/crawler.(*Crawler).Start.func1(0x10d26840, 0x0, 0x0, 0x10d50140)
/home/kofi/beats/src/github.com/elastic/beats/filebeat/crawler/crawler.go:59 +0xf4
created by github.com/elastic/beats/filebeat/crawler.(*Crawler).Start
/home/kofi/beats/src/github.com/elastic/beats/filebeat/crawler/crawler.go:60 +0x498

After some googling I found out that the 64-bit atomic must be aligned to a 64-bit address on ARM. This is however not achieved in the current Prospector struct. I tried adding a uint32 padding value before this field and now it works like a charm.

I have never programmed anything in Go before and I don't know if there's something more elegant to come along this problem. However, this should definitively be addressed in the code.

Regards,
Ingo

Please open a new issue for this. I think there could be two solutions. Make the counter a uint32 instead of uint64, or move the counter to the first value declared in the struct. Could you try latter?

Makes me wonder how well alignment requirements are supported by the compiler. There is no such thing as a special atomic type in go. That is, one has to be careful about placement of atomic fields in structs and hope for allocator(stack) to be always aligned (This should be the case). While not required for all architectures, proper alignment can still be beneficial/required, e.g. to ensure the atomic variable accessed does not overlap cachelines.

Structs employing atomics should also ensure to fit into a multiple of 8bytes, so using them in arrays is safe.

I think 32bit x86 also requires an 8byte boundary alignment (at least for 64bit atomic ops).

1 Like

Currently no time. Perhaps I can check this tomorrow but I guess it will work.

This issue made me curious. Never done anything before using Go. You're right, the data type itself is not atomic, but the operation on it which also requires the alignment.

I guess my problem on the Raspberry Pi running a 32-Bit Linux is related to this issue
https://github.com/golang/go/issues/599

As long as this isn't solved upstream, switching to uint32 for the number of prospectors should be safe. I guess 4 billion prospectors is suffienct for the moment :wink:

I ran into this same issue. Moving the counter to the first field of the struct resolved it for me. @kofi did you ever open an issue for this?

Thanks for remembering. No I haven't so far, but now I did

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.