| Age | Commit message (Collapse) | Author |
|
applyFdCloseState evicted the fd->path mapping (fdState + proc-fd cache)
on every close exit, ignoring the return value. A failed close — most
importantly EBADF ("fd isn't a valid open file descriptor"), but also
EINTR/EIO — did not release any descriptor we track, so dropping the
mapping there would let a later genuine close or a reuse of the fd
number resolve against stale/empty state.
Gate the eviction on ret==0, mirroring the ret==0 guard already used by
applyCloseRangeState for close_range. close's exit tracepoint is
generated as a ret_event (UNCLASSIFIED), so the exit carries the close
return value in RetEvent.Ret.
Tests: the close-exit event was being built as an fd_event, which does
not match the real BPF wire format (sys_exit_close emits EXIT_RET_EVENT).
Add a makeExitCloseEvent helper that emits the correct ret_event, route
all 18 close-exit call sites and TestHandleFdExitCloseClearsProcFdCache
through it, and add CloseFailureTest asserting a failed close (ret=-1)
leaves the fd tracked.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
creat(pathname, mode) is equivalent to open(pathname,
O_CREAT|O_WRONLY|O_TRUNC, mode): on success it returns a new fd, on
failure -1. handlePathExit already special-cased creat to register the
returned fd->path mapping in fdState (matching handleOpenExit for
open/openat/openat2), but on failure (ret<0) it left ep.File unset,
silently dropping the path. handleOpenExit keeps the path via
NewPathname for failed opens so error scenarios stay observable; align
the creat branch with that behavior.
Strengthen CreatEventTest to assert the returned fd is registered with
the correct path and synthesized open flags, and add a negative
FailedCreatEventTest covering the ret<0 path (no fd registered, path
retained).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
close_range was captured as a single-fd fd_event carrying only first, so
the runtime evicted every tracked fd >= first, ignoring the last upper
bound and the flags. Bounded calls wrongly dropped still-open higher fds,
and CLOSE_RANGE_CLOEXEC (which keeps fds open) was treated as a full close.
Reclassify close_range to the two_fd_event kind, mapping fd_a/fd_b/extra to
first/last/flags. The runtime now closes only the inclusive [first, last]
range (a negative last from ~0U means unbounded) and skips eviction when
CLOSE_RANGE_CLOEXEC is set or the syscall fails.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Split 22 production files across the codebase — event loop, TUI models,
probe manager, dashboard, export, flag parsing, code generation, and
ioworkload scenarios — so that no function body exceeds 50 lines. Each
extracted helper carries its own comment explaining its role.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
The printCb and warningCb function fields on eventLoop bundled two
distinct concerns (pair emission and warning delivery) directly on the
event-processing struct. This commit extracts them into a dedicated
outputFormatter type that owns these callbacks plus emit() and
notifyWarning() helper methods.
outputFormatter is embedded (not pointed-to) in eventLoop so that
existing call sites — including tests that write el.printCb = ... and
el.warningCb = ... directly — require no changes beyond the three
struct-literal sites in eventloop_filter_test.go that used field
initialiser syntax.
fdTracker and commResolver were already proper collaborator types; only
the output concern needed extraction.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Changing the global filter used to call stopTrace + beginTraceCmd, which
detached and re-attached every tracepoint and re-loaded the BPF object.
On heavily loaded I/O systems that took several seconds and showed an
'Attaching tracepoints...' overlay each time. The probe set never depends
on the global filter (ShouldIAttachTracepoint only reads CLI regex flags),
so the restart was gratuitous.
Now the eventloop holds its filter behind atomic.Pointer with SetFilter /
Filter accessors, and the trace starter registers el.SetFilter via the
runtime bindings as a SetLiveFilterSetter callback. applyGlobalFilter
and undoGlobalFilter call runtime.applyLiveFilter first; only if no
trace is running do they fall back to the full restart path.
|
|
|
|
|
|
responsibilities (task 428)
The eventLoop struct held 20+ fields across 5+ responsibilities (SRP violation).
Extract two cohesive sub-structs:
- pairTracker: enter/exit pair matching, age-based LRU pruning, and
DurationToPrev tracking. Replaces enterEvs/enterEvAges/prevPairTimes/
maxPendingEnterEvs/cacheAge fields with a single embedded value.
- fdTracker (extended): absorbs procFdCache/procFdAges/maxProcFdCacheSize,
moving all procfs-resolution cache logic (resolve, cache, prune, delete)
off eventLoop and onto the tracker that already owns the fd table.
eventLoop drops from 20 fields to 12. All methods that previously reached
into eventLoop fields now live on the struct that owns the data.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
|
|
(task 432)
The exitHandlers map keyed by reflect.Type was a reflection-based dispatch
table that incurred allocation and reflection overhead on every event pair
in the hot processing path. Replace it with a plain type switch in
handleTracepointExit, which the compiler resolves statically.
Removes: initExitHandlers, typeKey, mustBeType, newTypedExitHandler,
exitHandlerRegistry, the exitHandlers struct field, and the tracepointExitHandler
type alias — all dead after the switch. Fixes a pre-existing uint→uint64
mismatch in stats(). Updates tests to target the new default branch directly.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
|
|
|
|
|