Skip to content
This repository has been archived by the owner on Jul 31, 2023. It is now read-only.

trace: reorder defaultIDGenerator fields for 8byte alignment #866

Conversation

odeke-em
Copy link
Member

Fixes #865

This bug manifested as a consequence of
https://golang.org/pkg/sync/atomic/#pkg-note-BUG
and was exposed by PR #851 which switched to atomically
incrementing defaultIDGenerator.nextSpanID

The organization of the fields was misaligned on 32-bit
machines because the field traceIDRand *rand.Rand, a
pointer was included as the second field of the struct.
This is because the size of a pointer on 32-bit machines
is 4 bytes, hence after the second field, we'll have
offset from 12 bytes and for atomic access of *int64
fields, which are accessed in 4 byte increments by
atomic operations, on 32-bit machines, their addresses
are on non-8-byte divisible alignments i.e.
nextSpanID -- [28, 36]
spanIDInc -- [36, 44]

but on 64-bit machines, sizeof(pointer) = 8 bytes hence
their addresses are on 8-byte divisible alignments i.e.
nextSpanID -- [32, 40]
spanIDInc -- [40, 48]

Thus the required reorganization but making the pointer
the last field fixes the problem for both 32-bit and 64-bit.

This fix can be verified by prefixing GOARCH=386 before
running code or tests.

Fixes census-instrumentation#865

This bug manifested as a consequence of
https://golang.org/pkg/sync/atomic/#pkg-note-BUG
and was exposed by PR census-instrumentation#851 which switched to atomically
incrementing defaultIDGenerator.nextSpanID

The organization of the fields was misaligned on 32-bit
machines because the field `traceIDRand *rand.Rand`, a
pointer was included as the second field of the struct.
This is because the size of a pointer on 32-bit machines
is 4 bytes, hence after the second field, we'll have
offset from 12 bytes and for atomic access of *int64
fields, which are accessed in 4 byte increments by
atomic operations, on 32-bit machines, their addresses
are on non-8-byte divisible alignments i.e.
*   nextSpanID -- [28, 36]
*   spanIDInc  -- [36, 44]

but on 64-bit machines, sizeof(pointer) = 8 bytes hence
their addresses are on 8-byte divisible alignments i.e.
*   nextSpanID -- [32, 40]
*   spanIDInc  -- [40, 48]

Thus the required reorganization but making the pointer
the last field fixes the problem for both 32-bit and 64-bit.

This fix can be verified by prefixing `GOARCH=386` before
running code or tests.
@odeke-em odeke-em force-pushed the fix-trace-generator-misalignment-bug branch from 67abf0e to 0856a85 Compare August 16, 2018 21:07
@semistrict semistrict merged commit 1789eaf into census-instrumentation:master Aug 16, 2018
@semistrict
Copy link
Contributor

thanks @odeke-em!

@odeke-em
Copy link
Member Author

Thanks for the review and merge @Ramonza!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

trace: atomic.AddUint64(nextSpanID) causes segmentation violation due to misalignment on 32-bit architectures
2 participants