Repository navigation
Conversation
…d bun_sys::close Both entry points had their own copy of the close call and of the rule for its result, one per platform: five copies in two files. They now share close_once (the call) and close_error (the rule). The rule does not change: only EBADF surfaces.
|
Status This PR changes no behaviour, so it has no reproduction of its own. It is the groundwork of a stack:
|
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: oven-sh/bun/.coderabbit.yaml Review profile: ASSERTIVE Plan: Essentials Run ID: 📒 Files selected for processing (2)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review. WalkthroughPOSIX file-descriptor closing now uses shared helpers for the close attempt and error handling. Only ChangesPOSIX close handling
Suggested reviewers: Priority: ⬇️ Low Merge Risk: ⚪ Minimal · up to The refactor preserves existing close behavior across the inspected platform paths. No actionable merge-blocking risk remains, subject to normal build and test checks. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Comment |
There was a problem hiding this comment.
LGTM — a small, behavior-preserving consolidation of the POSIX close path.
What was reviewed:
- Traced each platform arm of
close_onceto its target:linux_syscall::closereturnsResult<(), i32>,nocancel::closeis apub(crate) safe fngated on macOS in lib.rs, andsafe_libc::closeis declared for non-Linux unix — the FreeBSD/other-POSIX fallback resolves. - Compared the old per-arm
sys::Error { errno: EBADF, syscall: close, fd }literals withError::from_code_int(...).with_fd(fd): same fields, and thewith_fddebug assert is already covered by theis_valid()assert at the top ofclose_allowing_standard_io. - Confirmed
close_once/close_errorcollide with nothing re-exported bypub use posix_impl::*, and the removedclose$NOCANCELextern andc_intimport in fd.rs had no other users. - Windows arm untouched; the one-line
if rc < 0 { .. } else { .. }is within rustfmt's default single-line width.
Extended reasoning...
The change touches only src/sys/fd.rs and src/sys/lib.rs in the bun_sys crate, replacing three per-OS close arms in FdExt::close_allowing_standard_io and the inline logic in posix_impl::close with two shared crate-private helpers (close_once, close_error), net -64/+24 lines. It touches no security-sensitive surface (no auth, parsing, or untrusted input); the fd-close semantics (single close, never retried on EINTR, only EBADF surfaced) are preserved line for line. No CODEOWNERS entry covers src/sys, there are no third-party reviews or open threads, and the bug hunt exited on dry_streak. I could not run cargo check in this sandbox, so the cross-platform arms were verified by tracing symbol definitions and cfg gates by hand; they are consistent with the author's reported multi-target cargo check.
|
@dylan-conway a note on overlap with #42819: both PRs edit the import lines at the top of |
Behaviour change: none
Problem
bun_sysclose a descriptor on POSIX:FdExt::close_allowing_standard_io(src/sys/fd.rs) andbun_sys::close(src/sys/lib.rs). Each has its own copy of the call and of the rule for its result, one copy for each platform. That makes five copies.Fix
close_onceissues the close.close_errorholds the rule. Both functions call them.close$NOCANCELdeclaration infd.rshas no other user, so this PR removes it.Background
Fd::close()is the close that most of bun calls. It drops the result. A debug build asserts that there is none: an error here means a use after close.close_allowing_standard_ioreturns the result.fs.closeandfs.closeSyncuse it.close(2)releases the descriptor even when it returns an error. So bun issues it once and does not retry.Downsides
textsize (80,666,326 B). Each of the 284 functions that issueclosehas the same code in both (objdump -d, addresses normalised).Notes
Stack. PR 1 of 3. #44330 changes the rule: close reports every errno except EINTR and EINPROGRESS. #44331 uses that in
fs.copyFileandfs.cp.Order. The self-review of the stack (it ran on #44331) said to land this PR first and alone: it is based on main and changes no behaviour.
Overlap with #42819. That PR (Remove libuv on Windows) edits the same import lines at the top of
src/sys/fd.rs, and the Windows arm ofclose_allowing_standard_iobelow them. This PR removes the macOSclose$NOCANCELdeclaration, which is the last user ofc_inton macOS in that file. After both PRs the file needs neitherc_intnorc_void. The conflict is those import lines.Suites run on a debug build with ASAN of this commit, Linux x64:
test/js/node/fs/fs.test.ts(it has "fs.close on stdio descriptors"): 614 pass, 8 skip.cp.test.ts,promises.test.js,dir.test.ts: 99 pass, 10 skip.test-fs-close.js,test-fs-close-errors.js,test-fs-copyfile.js.Machine code. Same toolchain for both release builds.
size:text,dataandbssare equal.nm -S: no function changed size, once swaps between identical folded functions are cancelled.objdump -d: the inlinedsyscall(SYS_close, fd)sequence occurs at 485 sites in 284 functions in both builds, and each of those functions disassembles to the same instructions.gdb, single-step:fs.closeSyncruns 154 instructions in both builds,fs.copyFileSync1,825.Other targets.
cargo check -p bun_syspasses for x86_64 and aarch64 linux (gnu and musl), x86_64 and aarch64 android, x86_64 and aarch64 darwin, x86_64 freebsd, and x86_64 and aarch64 windows. The macOS and FreeBSD arms are compiled, not run.Related. #38630 adds a debug ledger to both close entry points. After this PR there is one place for it.