summaryrefslogtreecommitdiff
path: root/internal/event/pair_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-13 10:21:56 +0300
committerPaul Buetow <paul@buetow.org>2026-05-13 10:21:56 +0300
commit7c15d6058cf56e8c7801259f1f842a3a010c5f41 (patch)
tree0b9f85dadade5958a281ab6abaa51dcb620603f2 /internal/event/pair_test.go
parent42d7821dc8d81781f2c3cfc269e99c0ee1dbd017 (diff)
fix: guard Pair.CalculateDurations against uint64 underflow on clock skew
BPF timestamps can be non-monotonic across CPUs (NTP step, TSC skew). When exit < enter or enter < prevPairTime the uint64 subtraction wraps to a huge value, corrupting latency histograms and flamegraph weights. Clamp both Duration and DurationToPrev to 0 instead of underflowing. Add TestPairCalculateDurationsNegativeDelta to cover this case. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/event/pair_test.go')
-rw-r--r--internal/event/pair_test.go30
1 files changed, 30 insertions, 0 deletions
diff --git a/internal/event/pair_test.go b/internal/event/pair_test.go
index eb033dc..9aa3e11 100644
--- a/internal/event/pair_test.go
+++ b/internal/event/pair_test.go
@@ -56,6 +56,36 @@ func TestPairCalculateDurationsWithPreviousExit(t *testing.T) {
}
}
+// TestPairCalculateDurationsNegativeDelta verifies that non-monotonic BPF
+// timestamps (exit < enter due to cross-CPU clock skew) do not cause uint64
+// underflow. Both Duration and DurationToPrev must clamp to zero.
+func TestPairCalculateDurationsNegativeDelta(t *testing.T) {
+ enter := &types.OpenEvent{
+ Time: 2000,
+ Pid: 1,
+ Tid: 2,
+ }
+ // Simulate clock skew: exit timestamp is earlier than enter.
+ exit := &types.RetEvent{
+ Time: 1900,
+ Pid: 1,
+ Tid: 2,
+ Ret: 0,
+ }
+
+ pair := NewPair(enter)
+ pair.ExitEv = exit
+ // prevPairTime > enterTime also triggers underflow in DurationToPrev.
+ pair.CalculateDurations(3000)
+
+ if pair.Duration != 0 {
+ t.Fatalf("Duration = %d, want 0 when exit < enter (underflow guard)", pair.Duration)
+ }
+ if pair.DurationToPrev != 0 {
+ t.Fatalf("DurationToPrev = %d, want 0 when enter < prevPairTime (underflow guard)", pair.DurationToPrev)
+ }
+}
+
func TestPairRecycleHandlesMissingExitEvent(t *testing.T) {
pair := NewPair(&types.OpenEvent{
Time: 1000,