Synchronise the endpoint stats between the capture and stats threads - #35
Merged
Conversation
git-hulk
force-pushed
the
design-stats-locking
branch
from
September 2, 2026 11:45
22dedae to
a66029e
Compare
git-hulk
force-pushed
the
design-stats-locking
branch
from
September 2, 2026 11:46
a66029e to
79b88cf
Compare
git-hulk
force-pushed
the
design-stats-locking
branch
2 times, most recently
from
September 2, 2026 11:58
9ecb72f to
e1dfaf1
Compare
git-hulk
force-pushed
the
design-stats-locking
branch
from
September 2, 2026 12:15
e1dfaf1 to
b5aa730
Compare
git-hulk
force-pushed
the
design-stats-locking
branch
from
September 2, 2026 12:24
b5aa730 to
5feda23
Compare
git-hulk
force-pushed
the
design-stats-locking
branch
from
September 2, 2026 12:26
5feda23 to
aeb43a8
Compare
The stats thread walked syn_tab and read every query_stats in it while
the capture thread was inserting endpoints and bumping counters, with
nothing between them. Replaying a 16000 packet capture while polling
the stats endpoint reports six data races under ThreadSanitizer and
aborts: in stats_incr, in create_stats_object and on srv->stopped.
- Add stats_lock to the sniffer, held by the capture thread around
every syn_tab lookup, insert and counter update, and by the stats
thread across the whole walk so a response cannot be counted half
way through serialisation. The requests table stays lock free: only
the capture thread touches it.
- srv->stopped is written by server_terminate, which also runs from
the signal handler, and read by the stats thread's loop. It is now
sig_atomic_t accessed through the compiler's atomic builtins.
- Skip the endpoint instead of dereferencing NULL when the calloc for
a new query_stats fails.
`make test-race` rebuilds under ThreadSanitizer and replays a generated
stress capture while polling the endpoint; it reports 0 races where the
previous code reported 6. It is opt-in because it clobbers the ordinary
build, and runs as its own CI job.
Assistant By Opus 5
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
git-hulk
force-pushed
the
design-stats-locking
branch
from
September 2, 2026 12:27
aeb43a8 to
d2d7b60
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The stats thread walked syn_tab and read every query_stats in it while
the capture thread was inserting endpoints and bumping counters, with
nothing between them. Replaying a 16000 packet capture while polling
the stats endpoint reports six data races under ThreadSanitizer and
aborts: in stats_incr, in create_stats_object and on srv->stopped.
Add stats_lock to the sniffer, held by the capture thread around
every syn_tab lookup, insert and counter update, and by the stats
thread across the whole walk so a response cannot be counted half
way through serialisation. The requests table stays lock free: only
the capture thread touches it.
srv->stopped is written by server_terminate, which also runs from
the signal handler, and read by the stats thread's loop. It is now
sig_atomic_t accessed through the compiler's atomic builtins.
Skip the endpoint instead of dereferencing NULL when the calloc for
a new query_stats fails.
make test-racerebuilds under ThreadSanitizer and replays a generatedstress capture while polling the endpoint; it reports 0 races where the
previous code reported 6. It is opt-in because it clobbers the ordinary
build, and runs as its own CI job.
🤖 Generated with Claude Code