summaryrefslogtreecommitdiff
path: root/internal/eventloop_state.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-28 10:43:37 +0300
committerPaul Buetow <paul@buetow.org>2026-05-28 10:43:37 +0300
commitff8774b5ce3f6b37e5152d0dc06ae46b7a36d1da (patch)
tree7224ccb001a0945216d6e30b5b9c326396ceba76 /internal/eventloop_state.go
parent99e99c6ea35ae97e84d727449f9ad7c4c0a9fa23 (diff)
close_range: honor last bound and CLOSE_RANGE_CLOEXEC flag
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>
Diffstat (limited to 'internal/eventloop_state.go')
-rw-r--r--internal/eventloop_state.go27
1 files changed, 21 insertions, 6 deletions
diff --git a/internal/eventloop_state.go b/internal/eventloop_state.go
index a277e31..40e11c2 100644
--- a/internal/eventloop_state.go
+++ b/internal/eventloop_state.go
@@ -58,11 +58,19 @@ func (t *fdTracker) delete(fd int32) {
delete(t.files, fd)
}
-func (t *fdTracker) closeRangeFrom(first int32) {
+// closeRange removes all tracked fds in the inclusive range [first, last], as
+// closed by close_range(2). A negative last means "no upper bound": close_range's
+// last argument is an unsigned int, so the common close-everything form ~0U
+// arrives here as a negative __s32 and must close every tracked fd >= first.
+func (t *fdTracker) closeRange(first, last int32) {
for fd := range t.files {
- if fd >= first {
- delete(t.files, fd)
+ if fd < first {
+ continue
}
+ if last >= 0 && fd > last {
+ continue
+ }
+ delete(t.files, fd)
}
}
@@ -113,16 +121,23 @@ func (t *fdTracker) deleteProcFdCache(fd int32, pid uint32) {
t.deleteCacheKey(procFdCacheKey(pid, fd))
}
-func (t *fdTracker) deleteProcFdCacheFrom(first int32, pid uint32) {
+// deleteProcFdCacheRange drops cached procfs resolutions for pid's fds in the
+// inclusive range [first, last]. A negative last means "no upper bound" (see
+// closeRange for why close_range's last argument can arrive negative).
+func (t *fdTracker) deleteProcFdCacheRange(first, last int32, pid uint32) {
if t.procFdCache == nil {
return
}
for key := range t.procFdCache {
cachePid := uint32(key >> 32)
cacheFd := int32(uint32(key))
- if cachePid == pid && cacheFd >= first {
- t.deleteCacheKey(key)
+ if cachePid != pid || cacheFd < first {
+ continue
+ }
+ if last >= 0 && cacheFd > last {
+ continue
}
+ t.deleteCacheKey(key)
}
}