From d06cc56987d85662bdf2f8ed61fbabb71da93347 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 6 May 2026 06:30:15 -0700 Subject: [PATCH] wgengine/magicsock: add more docs, checks to Test32bitAlignment Per recent chat with @raggi about all this, I went and looked at this test again. Updates #cleanup Change-Id: Icb7d87b1ed2cebf481ee4e358a3aa603e63fb8a4 Signed-off-by: Brad Fitzpatrick --- wgengine/magicsock/magicsock_test.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/wgengine/magicsock/magicsock_test.go b/wgengine/magicsock/magicsock_test.go index 3552ecc19..b3c21cb24 100644 --- a/wgengine/magicsock/magicsock_test.go +++ b/wgengine/magicsock/magicsock_test.go @@ -1460,7 +1460,20 @@ func TestDiscoStringLogRace(t *testing.T) { wg.Wait() } +// Test32bitAlignment verifies that that the 64-bit atomic mono.Time fields are +// 64-bit aligned, so that StoreAtomic and LoadAtomic won't panic on 32-bit +// platforms. +// +// For normal Go atomic types (sync/atomic.Int64, etc), the Go compiler +// guarantees 64-bit alignment on 32-bit platforms with an unexported magic +// embedded struct field. We can't make mono.Time use that easily. We could change +// mono.Time to be type Time struct { atomic.Int64 }, but that's pretty invasive. +// Instead, we just have this test to keep us safe on 32-bit platforms. func Test32bitAlignment(t *testing.T) { + if rt := reflect.TypeFor[mono.Time](); rt.Kind() != reflect.Int64 { + t.Fatalf("mono.Time is not a 64-bit integer type anymore; this test may be irrelevant now or out of date") + } + de := endpoint{ c: &Conn{}, } @@ -1468,9 +1481,13 @@ func Test32bitAlignment(t *testing.T) { if off := unsafe.Offsetof(de.lastRecvWG); off%8 != 0 { t.Fatalf("endpoint.lastRecvWG is not 8-byte aligned") } + if off := unsafe.Offsetof(de.lastRecvUDPAny); off%8 != 0 { + t.Fatalf("endpoint.lastRecvUDPAny is not 8-byte aligned") + } - de.noteRecvActivity(epAddr{}, mono.Now()) // verify this doesn't panic on 32-bit - de.noteRecvActivity(epAddr{}, mono.Now()) // second call should be throttled + // Verify these don't panic. + de.lastRecvWG.StoreAtomic(mono.Now()) + de.lastRecvUDPAny.StoreAtomic(mono.Now()) } // newTestConn returns a new Conn.