summaryrefslogtreecommitdiff
path: root/internal/eventloop.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-01 23:36:41 +0200
committerPaul Buetow <paul@buetow.org>2026-03-01 23:36:41 +0200
commit8dddf41e215bfe46ba75e083112e9c8d42e8cf24 (patch)
tree1b58efdbd53bd36c0831ae8530ef4a7d86b1f573 /internal/eventloop.go
parent3690b89082215ff5c1fc84110074cf08b1b8909c (diff)
Refactor tracepointExited into per-type handlers
Diffstat (limited to 'internal/eventloop.go')
-rw-r--r--internal/eventloop.go488
1 files changed, 259 insertions, 229 deletions
diff --git a/internal/eventloop.go b/internal/eventloop.go
index f303f65..d0f861d 100644
--- a/internal/eventloop.go
+++ b/internal/eventloop.go
@@ -290,270 +290,300 @@ func (e *eventLoop) tracepointExited(exitEv event.Event, ch chan<- *event.Pair)
ep.Recycle()
return
}
+ if !e.handleTracepointExit(ep) {
+ return
+ }
+ prevPairTime, _ := e.prevPairTimes[ep.EnterEv.GetTid()]
+ ep.CalculateDurations(prevPairTime)
+ e.prevPairTimes[ep.EnterEv.GetTid()] = ep.ExitEv.GetTime()
+ ch <- ep
+}
- switch v := ep.EnterEv.(type) {
+func (e *eventLoop) handleTracepointExit(ep *event.Pair) bool {
+ switch enterEv := ep.EnterEv.(type) {
case *OpenEvent:
- openEv := ep.EnterEv.(*OpenEvent)
- retEvent, ok := ep.ExitEv.(*RetEvent)
- if !ok {
- e.recyclePair(ep, "Dropped malformed open exit event")
- return
- }
- comm := types.StringValue(openEv.Comm[:])
- ep.Comm = comm
- if fd := int32(retEvent.Ret); fd >= 0 {
- file := file.NewFd(fd, types.StringValue(openEv.Filename[:]), v.Flags)
- e.files[fd] = file
- ep.File = file
- } else {
- // Keep path information for failed opens so error scenarios remain observable.
- ep.File = file.NewPathname(openEv.Filename[:])
- }
- e.comms[openEv.Tid] = comm
-
+ return e.handleOpenExit(ep, enterEv)
case *NameEvent:
- nameEvent := ep.EnterEv.(*NameEvent)
- ep.File = file.NewOldnameNewname(nameEvent.Oldname[:], nameEvent.Newname[:])
- ep.Comm = e.comm(ep.EnterEv.GetTid())
-
+ return e.handleNameExit(ep, enterEv)
case *PathEvent:
- if ep.EnterEv.GetTraceId().Name() == sysEnterNameToHandleAtName {
- retEv, ok := ep.ExitEv.(*types.RetEvent)
- if !ok || retEv.Ret < 0 {
- ep.Recycle()
- return
- }
- pathEv := ep.EnterEv.(*PathEvent)
- pathname := types.StringValue(pathEv.Pathname[:])
- e.pendingHandles[ep.EnterEv.GetTid()] = pathname
- ep.Recycle()
- return
- }
+ return e.handlePathExit(ep, enterEv)
+ case *FdEvent:
+ return e.handleFdExit(ep, enterEv)
+ case *Dup3Event:
+ return e.handleDup3Exit(ep, enterEv)
+ case *OpenByHandleAtEvent:
+ return e.handleOpenByHandleAtExit(ep, enterEv)
+ case *NullEvent:
+ return e.handleNullExit(ep, enterEv)
+ case *FcntlEvent:
+ return e.handleFcntlExit(ep, enterEv)
+ default:
+ e.recyclePair(ep, "Dropped malformed enter event")
+ return false
+ }
+}
- nameEvent := ep.EnterEv.(*PathEvent)
- if ep.Is(SYS_ENTER_CREAT) {
- retEvent, ok := ep.ExitEv.(*RetEvent)
- if !ok {
- e.recyclePair(ep, "Dropped malformed creat exit event")
- return
- }
- if fd := int32(retEvent.Ret); fd >= 0 {
- file := file.NewFd(fd, types.StringValue(nameEvent.Pathname[:]),
- syscall.O_CREAT|syscall.O_WRONLY|syscall.O_TRUNC)
- e.files[fd] = file
- ep.File = file
- }
- } else {
- ep.File = file.NewPathname(nameEvent.Pathname[:])
- }
- ep.Comm = e.comm(ep.EnterEv.GetTid())
+func (e *eventLoop) handleOpenExit(ep *event.Pair, openEv *OpenEvent) bool {
+ retEvent, ok := ep.ExitEv.(*RetEvent)
+ if !ok {
+ e.recyclePair(ep, "Dropped malformed open exit event")
+ return false
+ }
+
+ comm := types.StringValue(openEv.Comm[:])
+ ep.Comm = comm
+ if fd := int32(retEvent.Ret); fd >= 0 {
+ fdFile := file.NewFd(fd, types.StringValue(openEv.Filename[:]), openEv.Flags)
+ e.files[fd] = fdFile
+ ep.File = fdFile
+ } else {
+ // Keep path information for failed opens so error scenarios remain observable.
+ ep.File = file.NewPathname(openEv.Filename[:])
+ }
+ e.comms[openEv.Tid] = comm
+ return true
+}
- case *FdEvent:
- fd := ep.EnterEv.(*FdEvent).Fd
- if file_, ok := e.files[fd]; ok {
- ep.File = file_
- if ep.Is(SYS_ENTER_CLOSE) {
- delete(e.files, fd)
- }
- } else {
- ep.File = file.NewFdWithPid(fd, v.Pid)
- }
- if ep.Is(SYS_ENTER_CLOSE_RANGE) {
- // close_range provides (first, last), but fd_event only carries the first
- // argument, so we approximate by closing all tracked fds >= first.
- retEv, ok := ep.ExitEv.(*types.RetEvent)
- if ok && retEv.Ret == 0 {
- for fdToClose := range e.files {
- if fdToClose >= fd {
- delete(e.files, fdToClose)
- }
- }
- }
- }
- ep.Comm = e.comm(ep.EnterEv.GetTid())
- if !e.filter.eventPair(ep) {
+func (e *eventLoop) handleNameExit(ep *event.Pair, nameEv *NameEvent) bool {
+ ep.File = file.NewOldnameNewname(nameEv.Oldname[:], nameEv.Newname[:])
+ ep.Comm = e.comm(nameEv.GetTid())
+ return true
+}
+
+func (e *eventLoop) handlePathExit(ep *event.Pair, pathEv *PathEvent) bool {
+ if pathEv.GetTraceId().Name() == sysEnterNameToHandleAtName {
+ retEv, ok := ep.ExitEv.(*types.RetEvent)
+ if !ok || retEv.Ret < 0 {
ep.Recycle()
- return
+ return false
}
- if ep.Is(SYS_ENTER_DUP) || ep.Is(SYS_ENTER_DUP2) {
- fdFile, ok := ep.File.(file.FdFile)
- if !ok {
- e.recyclePair(ep, "Dropped malformed dup source event")
- return
- }
- retEvent, ok := ep.ExitEv.(*RetEvent)
- if !ok {
- e.recyclePair(ep, "Dropped malformed dup exit event")
- return
- }
- // Duplicating fd
- newFd := int32(retEvent.Ret)
- if newFd != -1 {
- e.files[newFd] = fdFile.Dup(newFd)
- }
+ e.pendingHandles[pathEv.GetTid()] = types.StringValue(pathEv.Pathname[:])
+ ep.Recycle()
+ return false
+ }
+
+ if ep.Is(SYS_ENTER_CREAT) {
+ retEvent, ok := ep.ExitEv.(*RetEvent)
+ if !ok {
+ e.recyclePair(ep, "Dropped malformed creat exit event")
+ return false
}
- if ep.Is(SYS_ENTER_PIDFD_GETFD) {
- retEv, ok := ep.ExitEv.(*RetEvent)
- if !ok {
- e.recyclePair(ep, "Dropped malformed pidfd_getfd exit event")
- return
- }
- if newFd := int32(retEv.Ret); newFd >= 0 {
- transferredFile := file.NewFdWithPid(newFd, v.Pid)
- e.files[newFd] = transferredFile
- ep.File = transferredFile
- }
+ if fd := int32(retEvent.Ret); fd >= 0 {
+ fdFile := file.NewFd(fd, types.StringValue(pathEv.Pathname[:]),
+ syscall.O_CREAT|syscall.O_WRONLY|syscall.O_TRUNC)
+ e.files[fd] = fdFile
+ ep.File = fdFile
}
+ } else {
+ ep.File = file.NewPathname(pathEv.Pathname[:])
+ }
+ ep.Comm = e.comm(pathEv.GetTid())
+ return true
+}
- if retEv, ok := ep.ExitEv.(*RetEvent); ok {
- ep.Bytes = bytesFromRet(retEv)
+func (e *eventLoop) handleFdExit(ep *event.Pair, fdEv *FdEvent) bool {
+ fd := fdEv.Fd
+ if fdFile, ok := e.files[fd]; ok {
+ ep.File = fdFile
+ if ep.Is(SYS_ENTER_CLOSE) {
+ delete(e.files, fd)
+ }
+ } else {
+ ep.File = file.NewFdWithPid(fd, fdEv.Pid)
+ }
+ if ep.Is(SYS_ENTER_CLOSE_RANGE) {
+ // close_range provides (first, last), but fd_event only carries the first
+ // argument, so we approximate by closing all tracked fds >= first.
+ retEv, ok := ep.ExitEv.(*types.RetEvent)
+ if ok && retEv.Ret == 0 {
+ for fdToClose := range e.files {
+ if fdToClose >= fd {
+ delete(e.files, fdToClose)
+ }
+ }
}
+ }
+ ep.Comm = e.comm(fdEv.GetTid())
+ if !e.filter.eventPair(ep) {
+ ep.Recycle()
+ return false
+ }
- case *Dup3Event:
- dup3Event := ep.EnterEv.(*Dup3Event)
- fd := int32(dup3Event.Fd)
- if file_, ok := e.files[fd]; ok {
- ep.File = file_
- } else {
- ep.File = file.NewFdWithPid(fd, v.Pid)
- }
- ep.Comm = e.comm(ep.EnterEv.GetTid())
- if !e.filter.eventPair(ep) {
- ep.Recycle()
- return
- }
- // Duplicating fd
+ if ep.Is(SYS_ENTER_DUP) || ep.Is(SYS_ENTER_DUP2) {
fdFile, ok := ep.File.(file.FdFile)
if !ok {
- e.recyclePair(ep, "Dropped malformed dup3 source event")
- return
+ e.recyclePair(ep, "Dropped malformed dup source event")
+ return false
}
retEvent, ok := ep.ExitEv.(*RetEvent)
if !ok {
- e.recyclePair(ep, "Dropped malformed dup3 exit event")
- return
+ e.recyclePair(ep, "Dropped malformed dup exit event")
+ return false
}
- newFd := int32(retEvent.Ret)
- if newFd != -1 {
- duppedFdFile := fdFile.Dup(newFd)
- duppedFdFile.AddFlags(dup3Event.Flags & syscall.O_CLOEXEC)
- e.files[newFd] = duppedFdFile
+ // Duplicating fd
+ if newFd := int32(retEvent.Ret); newFd != -1 {
+ e.files[newFd] = fdFile.Dup(newFd)
}
-
- case *OpenByHandleAtEvent:
- tid := ep.EnterEv.GetTid()
- retEvent, ok := ep.ExitEv.(*RetEvent)
+ }
+ if ep.Is(SYS_ENTER_PIDFD_GETFD) {
+ retEv, ok := ep.ExitEv.(*RetEvent)
if !ok {
- e.recyclePair(ep, "Dropped malformed open_by_handle_at exit event")
- return
+ e.recyclePair(ep, "Dropped malformed pidfd_getfd exit event")
+ return false
}
-
- if fd := int32(retEvent.Ret); fd >= 0 {
- openByHandleEv := ep.EnterEv.(*OpenByHandleAtEvent)
- if pathname, ok := e.pendingHandles[tid]; ok {
- delete(e.pendingHandles, tid)
- file := file.NewFd(fd, pathname, openByHandleEv.Flags)
- e.files[fd] = file
- ep.File = file
- } else {
- fdFile := file.NewFdWithPid(fd, v.Pid)
- if fdFile.Flags() == file.Flags(-1) {
- fdFile.SetFlags(openByHandleEv.Flags)
- }
- e.files[fd] = fdFile
- ep.File = fdFile
- }
- ep.Comm = e.comm(tid)
- } else {
- ep.Recycle()
- return
+ if newFd := int32(retEv.Ret); newFd >= 0 {
+ transferredFile := file.NewFdWithPid(newFd, fdEv.Pid)
+ e.files[newFd] = transferredFile
+ ep.File = transferredFile
}
+ }
+ if retEv, ok := ep.ExitEv.(*RetEvent); ok {
+ ep.Bytes = bytesFromRet(retEv)
+ }
+ return true
+}
- case *NullEvent:
- if ep.Is(SYS_ENTER_IO_URING_SETUP) {
- retEvent, ok := exitEv.(*types.RetEvent)
- if !ok {
- e.recyclePair(ep, "Dropped malformed io_uring_setup exit event")
- return
- }
- if fd := int32(retEvent.Ret); fd >= 0 {
- fdFile := file.NewFdWithPid(fd, v.Pid)
- e.files[fd] = fdFile
- ep.File = fdFile
- }
- }
- if ep.Is(SYS_ENTER_GETCWD) {
- retEvent, ok := ep.ExitEv.(*types.RetEvent)
- if !ok {
- e.recyclePair(ep, "Dropped malformed getcwd exit event")
- return
- }
- if retEvent.Ret > 0 {
- if cwd, err := os.Readlink(fmt.Sprintf("/proc/%d/cwd", ep.EnterEv.GetTid())); err == nil {
- ep.File = file.NewPathname([]byte(cwd))
- }
- }
- }
- ep.Comm = e.comm(ep.EnterEv.GetTid())
- if !e.filter.eventPair(ep) {
- ep.Recycle()
- return
- }
+func (e *eventLoop) handleDup3Exit(ep *event.Pair, dup3Ev *Dup3Event) bool {
+ fd := int32(dup3Ev.Fd)
+ if fdFile, ok := e.files[fd]; ok {
+ ep.File = fdFile
+ } else {
+ ep.File = file.NewFdWithPid(fd, dup3Ev.Pid)
+ }
+ ep.Comm = e.comm(dup3Ev.GetTid())
+ if !e.filter.eventPair(ep) {
+ ep.Recycle()
+ return false
+ }
- case *FcntlEvent:
- ep.Comm = e.comm(ep.EnterEv.GetTid())
- fd := int32(v.Fd)
- if file_, ok := e.files[fd]; ok {
- ep.File = file_
- } else {
- ep.File = file.NewFdWithPid(fd, v.Pid)
- }
- if !e.filter.eventPair(ep) {
- ep.Recycle()
- return
+ fdFile, ok := ep.File.(file.FdFile)
+ if !ok {
+ e.recyclePair(ep, "Dropped malformed dup3 source event")
+ return false
+ }
+ retEvent, ok := ep.ExitEv.(*RetEvent)
+ if !ok {
+ e.recyclePair(ep, "Dropped malformed dup3 exit event")
+ return false
+ }
+ if newFd := int32(retEvent.Ret); newFd != -1 {
+ duppedFdFile := fdFile.Dup(newFd)
+ duppedFdFile.AddFlags(dup3Ev.Flags & syscall.O_CLOEXEC)
+ e.files[newFd] = duppedFdFile
+ }
+ return true
+}
+
+func (e *eventLoop) handleOpenByHandleAtExit(ep *event.Pair, openByHandleEv *OpenByHandleAtEvent) bool {
+ tid := openByHandleEv.GetTid()
+ retEvent, ok := ep.ExitEv.(*RetEvent)
+ if !ok {
+ e.recyclePair(ep, "Dropped malformed open_by_handle_at exit event")
+ return false
+ }
+
+ fd := int32(retEvent.Ret)
+ if fd < 0 {
+ ep.Recycle()
+ return false
+ }
+
+ if pathname, ok := e.pendingHandles[tid]; ok {
+ delete(e.pendingHandles, tid)
+ fdFile := file.NewFd(fd, pathname, openByHandleEv.Flags)
+ e.files[fd] = fdFile
+ ep.File = fdFile
+ } else {
+ fdFile := file.NewFdWithPid(fd, openByHandleEv.Pid)
+ if fdFile.Flags() == file.Flags(-1) {
+ fdFile.SetFlags(openByHandleEv.Flags)
}
+ e.files[fd] = fdFile
+ ep.File = fdFile
+ }
+ ep.Comm = e.comm(tid)
+ return true
+}
- retEvent, ok := exitEv.(*types.RetEvent)
+func (e *eventLoop) handleNullExit(ep *event.Pair, nullEv *NullEvent) bool {
+ if ep.Is(SYS_ENTER_IO_URING_SETUP) {
+ retEvent, ok := ep.ExitEv.(*types.RetEvent)
if !ok {
- e.recyclePair(ep, "Dropped malformed fcntl exit event")
- return
+ e.recyclePair(ep, "Dropped malformed io_uring_setup exit event")
+ return false
}
- // Syscall returned -1, nothing was changed with the fd
- if retEvent.Ret == -1 {
- break
+ if fd := int32(retEvent.Ret); fd >= 0 {
+ fdFile := file.NewFdWithPid(fd, nullEv.Pid)
+ e.files[fd] = fdFile
+ ep.File = fdFile
}
-
- fdFile, ok := ep.File.(file.FdFile)
+ }
+ if ep.Is(SYS_ENTER_GETCWD) {
+ retEvent, ok := ep.ExitEv.(*types.RetEvent)
if !ok {
- e.recyclePair(ep, "Dropped malformed fcntl file event")
- return
+ e.recyclePair(ep, "Dropped malformed getcwd exit event")
+ return false
}
-
- // See fcntl(2) for implementation details
- switch v.Cmd {
- case syscall.F_SETFL:
- const canChange = syscall.O_APPEND | syscall.O_ASYNC | syscall.O_DIRECT | syscall.O_NOATIME | syscall.O_NONBLOCK
- fdFile.SetFlags((int32(v.Arg) & int32(canChange)))
- ep.File = fdFile
- e.files[fd] = fdFile
- case syscall.F_DUPFD:
- newFd := int32(retEvent.Ret)
- e.files[newFd] = fdFile.Dup(newFd)
- case syscall.F_DUPFD_CLOEXEC:
- newFd := int32(retEvent.Ret)
- duppedFdFile := fdFile.Dup(newFd)
- duppedFdFile.AddFlags(syscall.O_CLOEXEC)
- e.files[newFd] = duppedFdFile
+ if retEvent.Ret > 0 {
+ if cwd, err := os.Readlink(fmt.Sprintf("/proc/%d/cwd", nullEv.GetTid())); err == nil {
+ ep.File = file.NewPathname([]byte(cwd))
+ }
}
+ }
+ ep.Comm = e.comm(nullEv.GetTid())
+ if !e.filter.eventPair(ep) {
+ ep.Recycle()
+ return false
+ }
+ return true
+}
- default:
- e.recyclePair(ep, "Dropped malformed enter event")
- return
+func (e *eventLoop) handleFcntlExit(ep *event.Pair, fcntlEv *FcntlEvent) bool {
+ ep.Comm = e.comm(fcntlEv.GetTid())
+ fd := int32(fcntlEv.Fd)
+ if fdFile, ok := e.files[fd]; ok {
+ ep.File = fdFile
+ } else {
+ ep.File = file.NewFdWithPid(fd, fcntlEv.Pid)
}
- prevPairTime, _ := e.prevPairTimes[ep.EnterEv.GetTid()]
- ep.CalculateDurations(prevPairTime)
- e.prevPairTimes[ep.EnterEv.GetTid()] = ep.ExitEv.GetTime()
- ch <- ep
+ if !e.filter.eventPair(ep) {
+ ep.Recycle()
+ return false
+ }
+
+ retEvent, ok := ep.ExitEv.(*types.RetEvent)
+ if !ok {
+ e.recyclePair(ep, "Dropped malformed fcntl exit event")
+ return false
+ }
+ // Syscall returned -1, nothing was changed with the fd
+ if retEvent.Ret == -1 {
+ return true
+ }
+
+ fdFile, ok := ep.File.(file.FdFile)
+ if !ok {
+ e.recyclePair(ep, "Dropped malformed fcntl file event")
+ return false
+ }
+
+ // See fcntl(2) for implementation details
+ switch fcntlEv.Cmd {
+ case syscall.F_SETFL:
+ const canChange = syscall.O_APPEND | syscall.O_ASYNC | syscall.O_DIRECT | syscall.O_NOATIME | syscall.O_NONBLOCK
+ fdFile.SetFlags(int32(fcntlEv.Arg) & int32(canChange))
+ ep.File = fdFile
+ e.files[fd] = fdFile
+ case syscall.F_DUPFD:
+ newFd := int32(retEvent.Ret)
+ e.files[newFd] = fdFile.Dup(newFd)
+ case syscall.F_DUPFD_CLOEXEC:
+ newFd := int32(retEvent.Ret)
+ duppedFdFile := fdFile.Dup(newFd)
+ duppedFdFile.AddFlags(syscall.O_CLOEXEC)
+ e.files[newFd] = duppedFdFile
+ }
+ return true
}
func (e *eventLoop) recyclePair(ep *event.Pair, warning string) {