From 9cbf9ec8e9eac92431b9a742c1b625888cb69dfa Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 8 Mar 2026 11:24:31 +0200 Subject: eventloop: remove gosched by snapshotting emitted fd state --- internal/eventloop.go | 13 +++++++++---- internal/eventloop_test.go | 25 +++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/internal/eventloop.go b/internal/eventloop.go index 64c7d6f..2c3cf49 100644 --- a/internal/eventloop.go +++ b/internal/eventloop.go @@ -8,7 +8,6 @@ import ( "os" "path/filepath" "reflect" - "runtime" "sync" "syscall" "time" @@ -408,9 +407,6 @@ func (e *eventLoop) events(ctx context.Context, rawCh <-chan []byte) <-chan *eve continue } e.processRawEvent(raw, ch) - // Yield so downstream consumers can process emitted pairs before - // the next raw event mutates shared tracker state. - runtime.Gosched() case <-ctx.Done(): fmt.Println("Stopping event loop") return @@ -593,9 +589,18 @@ func (e *eventLoop) tracepointExited(exitEv event.Event, ch chan<- *event.Pair) prevPairTime, _ := e.prevPairTimes[ep.EnterEv.GetTid()] ep.CalculateDurations(prevPairTime) e.prevPairTimes[ep.EnterEv.GetTid()] = ep.ExitEv.GetTime() + e.freezePairForEmission(ep) ch <- ep } +func (e *eventLoop) freezePairForEmission(ep *event.Pair) { + fdFile, ok := ep.File.(*file.FdFile) + if !ok { + return + } + ep.File = fdFile.Dup(fdFile.FD()) +} + func (e *eventLoop) initExitHandlers() { e.exitHandlers = map[reflect.Type]tracepointExitHandler{ reflect.TypeOf(&types.OpenEvent{}): func(ep *event.Pair) bool { diff --git a/internal/eventloop_test.go b/internal/eventloop_test.go index 32dddd4..3a4ad38 100644 --- a/internal/eventloop_test.go +++ b/internal/eventloop_test.go @@ -203,6 +203,31 @@ func TestHandleFdExitCloseRangeClearsProcFdCacheRange(t *testing.T) { verifyProcFdCached(t, el, pid+1, 20) } +func TestFreezePairForEmissionCopiesFdFile(t *testing.T) { + el := mustNewEventLoop(t, eventLoopConfig{}) + fdFile := file.NewFd(9, "/tmp/x", syscall.O_RDONLY) + ep := event.NewPair(&types.NullEvent{}) + ep.File = fdFile + + el.freezePairForEmission(ep) + + emitted, ok := ep.File.(*file.FdFile) + if !ok { + t.Fatalf("expected emitted file to be *file.FdFile, got %T", ep.File) + } + if emitted == fdFile { + t.Fatalf("expected emitted fd file to be detached copy") + } + if emitted.Flags() != file.Flags(syscall.O_RDONLY) { + t.Fatalf("expected copied flags %v, got %v", syscall.O_RDONLY, emitted.Flags()) + } + + fdFile.SetFlags(syscall.O_WRONLY) + if emitted.Flags() != file.Flags(syscall.O_RDONLY) { + t.Fatalf("expected emitted copy flags unchanged after source mutation") + } +} + // Tests a simple enter/exit pair of tracepoints. func makeOpenEventTestData1(t *testing.T) (td testData) { enterEv, enterEvBytes := makeEnterOpenEvent(t, defaulTime, defaultPid, defaultTid) -- cgit v1.2.3