Skip to content

Commit 575ec59

Browse files
mgazzaclaude
andauthored
fix: use atomic operations for concurrent counter access (#109)
- DHCP server: s.requestsTotal++ and s.offersTotal++ → atomic.AddUint64 - DHCP server: Stats() reads → atomic.LoadUint64 for all counters - RADIUS coverage_test: handlerCalled bool → atomic.Bool in CoA tests Fixes data races detected by -race flag in CI. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 003b563 commit 575ec59

File tree

2 files changed

+13
-13
lines changed

2 files changed

+13
-13
lines changed

pkg/dhcp/server.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ func (s *Server) Start(ctx context.Context) error {
295295

296296
// handleDHCP handles incoming DHCP packets (slow path)
297297
func (s *Server) handleDHCP(conn net.PacketConn, peer net.Addr, req *dhcpv4.DHCPv4) {
298-
s.requestsTotal++
298+
atomic.AddUint64(&s.requestsTotal, 1)
299299

300300
mac := req.ClientHWAddr.String()
301301
msgType := req.MessageType()
@@ -508,7 +508,7 @@ func (s *Server) handleDiscover(req *dhcpv4.DHCPv4) (*dhcpv4.DHCPv4, error) {
508508
return nil, fmt.Errorf("failed to build OFFER: %w", err)
509509
}
510510

511-
s.offersTotal++
511+
atomic.AddUint64(&s.offersTotal, 1)
512512
return resp, nil
513513
}
514514

@@ -1090,11 +1090,11 @@ func (s *Server) cleanupExpiredLeases() {
10901090
// Stats returns DHCP server statistics
10911091
func (s *Server) Stats() map[string]uint64 {
10921092
return map[string]uint64{
1093-
"requests_total": s.requestsTotal,
1094-
"offers_total": s.offersTotal,
1095-
"acks_total": s.acksTotal,
1096-
"naks_total": s.naksTotal,
1097-
"releases_total": s.releasesTotal,
1093+
"requests_total": atomic.LoadUint64(&s.requestsTotal),
1094+
"offers_total": atomic.LoadUint64(&s.offersTotal),
1095+
"acks_total": atomic.LoadUint64(&s.acksTotal),
1096+
"naks_total": atomic.LoadUint64(&s.naksTotal),
1097+
"releases_total": atomic.LoadUint64(&s.releasesTotal),
10981098
}
10991099
}
11001100

pkg/radius/coverage_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,9 +1730,9 @@ func TestCoAServer_HandleCoARequest_WithHandler(t *testing.T) {
17301730
}
17311731
defer srv.Stop()
17321732

1733-
handlerCalled := false
1733+
var handlerCalled atomic.Bool
17341734
srv.SetCoAHandler(func(ctx context.Context, req *CoARequest) *CoAResponse {
1735-
handlerCalled = true
1735+
handlerCalled.Store(true)
17361736
return &CoAResponse{Success: true, Message: "accepted"}
17371737
})
17381738

@@ -1741,7 +1741,7 @@ func TestCoAServer_HandleCoARequest_WithHandler(t *testing.T) {
17411741

17421742
time.Sleep(100 * time.Millisecond) // Allow time to process
17431743

1744-
if !handlerCalled {
1744+
if !handlerCalled.Load() {
17451745
t.Error("CoA handler was not called")
17461746
}
17471747

@@ -1795,17 +1795,17 @@ func TestCoAServer_HandleDisconnectRequest_WithHandler(t *testing.T) {
17951795
}
17961796
defer srv.Stop()
17971797

1798-
handlerCalled := false
1798+
var handlerCalled atomic.Bool
17991799
srv.SetDisconnectHandler(func(ctx context.Context, req *DisconnectRequest) *DisconnectResponse {
1800-
handlerCalled = true
1800+
handlerCalled.Store(true)
18011801
return &DisconnectResponse{Success: true, Message: "disconnected"}
18021802
})
18031803

18041804
sendCoAPacket(t, srv, CodeDisconnectRequest)
18051805

18061806
time.Sleep(100 * time.Millisecond)
18071807

1808-
if !handlerCalled {
1808+
if !handlerCalled.Load() {
18091809
t.Error("Disconnect handler was not called")
18101810
}
18111811

0 commit comments

Comments
 (0)