Repository navigation
Conversation
…ages The kernel can return an errno that bun's table does not declare (ENOTSUPP 524, or a code a FUSE daemon replies with). Error::get_errno already decodes such a number as EUNKNOWN. Error::get_error_code_tag_name returned None for it, so a JS error had no code and the message "Unknown Error". It now names the number EUNKNOWN. The errno in the error stays the number that the kernel returned. Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
…nc, mkdtemp, copy_file_range, splice and FICLONE bun_sys has no retrying form of these calls, so node:fs and Bun.write issue them with libc directly and finish on the first EINTR. - link, truncate, posix_rmdir and unlink_without_path leave the path off the error. node:fs reports the path its caller passed. - mkdtemp writes the XXXXXX back before it calls again. libc can leave its candidate name in the template when the call fails. - copy_file_range, splice and ioctl_ficlone are the retrying forms of the raw Linux calls. bun_sys::copy_file now uses them. - exists_z and exists_os_path become exists_at on the working directory. Its Linux arm already retries. The other arm now loops on EINTR. Before, an interrupted access() read as "does not exist". - clonefile on macOS takes the flags. Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
…sync, mkdtemp and the copy syscalls through bun_sys On POSIX these calls went to libc directly and mapped the one return code with errno_sys*, so a signal that interrupted the syscall surfaced as EINTR in JavaScript. libuv runs an fs request again on EINTR. - NodeFS::unlink, rmdir, link, truncate, fsync, fdatasync and mkdtemp call the bun_sys wrappers and attach the caller's path as before. - The copy_file_range loops of copyFile and cp, the forced and the opportunistic FICLONE, and Bun.write(file, file) (copy_file_range, sendfile, splice) call the retrying wrappers. - The macOS clonefile and copyfile sites call bun_sys::clonefile and bun_sys::copyfile. - errno_sys*, clonefile_rc, copyfile_rc and the c::truncate re-export have no caller left and are removed. linux::copy_file_range and linux::ioctl_ficlone are private to bun_sys. Co-authored-by: Dylan Conway <dylan.conway567@gmail.com> Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
…utable_file, and give fcopyfile one rule More calls of the same class finish on the first EINTR: - fetch with a Bun.file body issues the raw sendfile thunk and rejects with "EINTR fetching". bun_sys::sendfile now takes an offset, and fetch, Bun.serve and bun_sys::copy_file send files through it. The raw linux::sendfile thunk has no caller left and is removed. - is_executable_file, the probe behind Bun.which and spawn, reads an interrupted stat or open as "not executable". It now calls again. - lstatat outside Linux is a single fstatat. It now shares the loop of fstatat. - realpath now calls again on EINTR. err_with_path has no caller left. - fcopyfile(3) copies from the file positions and then truncates the destination to the bytes of that one call, so a second call after a partial copy leaves a short file. bun_sys::fcopyfile now calls again only while both positions are at 0, and bun_sys::copy_file uses it.
A preloaded shim fails one call of a named libc function in the directory of a row and logs it. Linux rows: unlink, rmdir, link, truncate, fsync, fdatasync, mkdtemp, exists, Bun.which, realpath, cp, copyFile, Bun.write (copy_file_range, sendfile, splice), fetch with a Bun.file body, and the FICLONE of copyFile and cp. One test pins the error of a call that fails with ENOSPC or with an errno outside bun's table. macOS rows: exists (faccessat), clonefile, copyfile and fcopyfile. The shim is compiled while the tests are collected, so a compiler that is not in the page cache does not use up the time of a test.
|
Status Reproduced on main in two ways. With a preloaded shim (
With real signals and no shim: a SIGUSR1 handler without SA_RESTART ( The repro is PR: #45929 |
|
Updated 11:58 PM PT - Oct 21st, 2026
✅ @robobun, your commit 4bea0734582f71204eef96ece2c0b39b700ee332 passed in 🧪 To try this PR locally: bunx bun-pr 45929That installs a local version of the PR into your bun-45929 --bun |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 5 seconds. View limit details
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
WalkthroughThe change adds shared POSIX syscall wrappers, routes filesystem and copy operations through Result-based APIs, updates EINTR handling, and adds Linux/macOS fault-injection tests for retries, fallbacks, and error reporting. ChangesFilesystem syscall handling
Suggested reviewers: Priority: ➖ Normal Merge Risk: ⚪ Minimal · up to
|
There was a problem hiding this comment.
Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.
Beyond the inline findings, I also checked the explicit-offset retries in the new bun_sys::sendfile and bun_sys::copy_file_range wrappers (callers in src/http/SendFile.rs, src/runtime/server/FileResponseStream.rs, and the cp/copyFile loops in src/runtime/node/node_fs.rs): the kernel only writes the offset out-param back on a positive return, so re-issuing with the same &mut i64 after EINTR neither skips nor double-sends bytes, and dropping the EINTR => continue arms at those call sites is equivalent.
Extended reasoning...
The change moves EINTR retry for unlink/rmdir/link/truncate/mkdtemp/fdatasync/sendfile/copy_file_range/splice/ioctl_ficlone/fcopyfile into src/sys/lib.rs wrappers and rewires node_fs, Bun.write, fetch, and Bun.serve callers onto them, with no security-sensitive surface. The inline findings already flag the mkdtemp double-create, the fcopyfile position gate, and the uneven SendFile.rs arms; this note only records the offset-retry check that was ruled out.
Additional findings (outside the current diff — GitHub can't attach inline comments there):
-
🟣
src/http/SendFile.rs— Pre-existing, left by this partial fix: on macOS and FreeBSD,fetchwith aBun.filebody still rejects with EINTR when a signal interrupts sendfile, exactly as on the base branch. Only the Linux arm ofSendFile::writewas moved onto the retryingbun_sys::sendfile; the macOS arm at src/http/SendFile.rs:113 and the FreeBSD arm at src/http/SendFile.rs:82 still call rawbun_sys::c::sendfileand turn every errno other than EAGAIN intoStatus::Err. Fix: make every arm ofSendFile::writesurvive EINTR, e.g. treat EINTR like EAGAIN (offset and remain are already advanced fromsbytes, so returningStatus::Againresumes correctly) or loop on it, for both the macOS and FreeBSD arms.Why this was flagged
On macOS or FreeBSD a user calls
fetch(url, { method: "POST", body: Bun.file(path) })with a file of 32 KB or more, which takes the sendfile upload path in src/http/lib.rs:3538. A signal arrives while the kernel sendfile waits (the PR names FUSE, NFS and file leases as realistic sources); Darwin sendfile returns -1 with errno EINTR and a partialsbytes. src/http/SendFile.rs:113 testserrcode != bun_sys::E::EAGAIN || ..., so EINTR falls intoStatus::Errat src/http/SendFile.rs:118 and the request fails withEINTR fetching "<url>", the message the PR says it removes. The base branch behaves the same on these platforms; only the Linux arm at src/http/SendFile.rs:37 was changed to the retrying wrapper, so this sibling site of the same bug class is left unfixed and the macOS test rows in test/js/node/fs/fs-eintr-syscalls.test.ts:298 do not cover fetch.Verification: Pre-existing (the base branch fails the same way by the same route; the PR fixes only the Linux arm). Triggering condition: on macOS a
fetchwith aBun.filebody of >= 32 KiB is interrupted by a signal while insendfile(2). At src/http/SendFile.rs:113 EINTR falls through toStatus::Errat line 118. The new macOS test does not interposesendfile, so nothing covers this arm.
No code change.
…body On macOS, fetch with a Bun.file body issues sendfile(2) through a raw thunk and rejects with EINTR when the call is interrupted. XNU returns EINTR from the read of the file on a file system that waits (NFS, SMB, FUSE). Only the Linux arm of SendFile::write used the retrying wrapper. The FreeBSD arm had the same code as the macOS arm. - bun_sys::sendfile for macOS and FreeBSD has the shape of the Linux call. It returns the bytes sent and advances the offset. EINTR with no bytes sent calls again. EAGAIN or EINTR after some bytes is a short count, the rule of uv__fs_sendfile in libuv. - SendFile::write has one body for the three systems. The raw c::sendfile thunks have no caller left and are removed. - Three results other than EINTR change on macOS and FreeBSD, each to the Linux rule. A count of 0 sends nothing (these kernels read 0 as the rest of the file). A call that sent less than it was asked for is followed by another call. EAGAIN after the whole count was sent ends the upload and is not an error. - The FreeBSD arm is compiled and has not run. No CI lane runs FreeBSD tests.
The upload rows send to a socket that keeps every byte of the request. A row passes only when Content-Length and the bytes after the head are the file or the slice. - Linux: a whole file, a slice, and an upload that the shim cuts into parts of 7777 bytes, so that SendFile::write runs many times. - macOS: EINTR before a byte is sent, EINTR after 4096 bytes, EAGAIN after the whole count, a slice, and an empty slice that must issue no call. - A sendfile that fails with EIO rejects with EIO on both systems. The Linux tests now run one at a time. Four debug builds that start together each take most of the 5 seconds of a test on a loaded machine. One at a time, each test takes about 1 second.
|
2942926 covers the macOS and FreeBSD arms of
The three inline threads have their own replies. |
There was a problem hiding this comment.
I reviewed the latest push (the unified macOS/FreeBSD sendfile wrapper, the single SendFile::write body, and the test changes) and found no new bugs; because this rewrites the syscall wrappers under bun install, Bun.write and fetch uploads across Linux/macOS/FreeBSD cfg arms that cannot all be type-checked from one host, and the description says the macOS test has not been run, a human look is still worthwhile.
What was reviewed:
- The new macOS/FreeBSD
sendfilewrapper against the two arms it replaces: EAGAIN/EINTR with bytes sent still yields a short count andStatus::Again, zero bytes still errors, and thelen == 0early return avoids the whole-file send the old macOS arm would have issued for an exhausted range. - The force-clone site in
copy_file_innernow taggedclonefileinstead ofcopyfile: masked, becauseNodeFS::copy_filerewrites syscall/path/dest on every error, so the Node error contract is unchanged. - Stale callers of the deleted thunks (
c::sendfile,linux::sendfile,clonefile_rc,copyfile_rc,c::truncate,errno_sys*): none remain outsidesrc/sys. get_error_code_tag_name'sEUNKNOWNfallback: every platform errno table (linux, darwin, freebsd, windows) declares the variant.
Extended reasoning...
The change moves EINTR retry for unlink/rmdir/link/truncate/fsync/fdatasync/mkdtemp/realpath/faccessat/sendfile/copy_file_range/splice/FICLONE/fcopyfile into bun_sys wrappers, deletes the node_fs errno_sys shim and the raw sendfile/clonefile/copyfile thunks, and collapses SendFile::write and FileResponseStream's sendfile path onto the wrappers; it touches no auth, crypto or injection surface. It is roughly +1084/-743 across src/sys, node_fs, Bun.write, fetch and Bun.serve, with four cfg-gated platform arms, a user-visible error-shape change (unknown errnos now report EUNKNOWN) and a new LD_PRELOAD/DYLD_INSERT_LIBRARIES fault-injection test that compiles C at test time. The size, the untested macOS arm per the author, and my still-open inline findings from the prior review decided defer over approve.
…-fs-eintr-retry # Conflicts: # src/runtime/node/node_fs.rs
No change in behaviour. The comments name the placeholder as six X.
Problem
EINTR: interrupted system call, unlink '<path>'(or their own syscall) when a signal interrupts them. They arefs.unlink,rmdir,link,truncate,fsync,fdatasync,mkdtemp,cp,Bun.write(file, file)andfetchwith aBun.filebody.existsSyncanswersfalse,Bun.whichanswersnull.errno_sys*(src/runtime/node/node_fs.rs:33) maps one finished return code to an error. libuv andbun_syscall again.Fix
bun_sysgains wrappers that retry EINTR.NodeFS,Bun.write,fetchandBun.servecall them.errno_sys*is deleted.test/js/node/fs/fs-eintr-syscalls.test.ts. Its 4 Linux tests fail on main. Its 2 macOS tests pass on the darwin lanes. The FreeBSD arm has not run.Background
Downsides
err.errno-524 (was -134) on 8 calls. Everybun_syswrapper reports it withcode: "EUNKNOWN".Bun.writereports EINTR whenfcopyfilestops mid-copy (main calls again and truncates the file). Afetchupload changes in three results besides EINTR (Notes).Notes
No GitHub issue: a shim audit found this, no user reported it. The closed precedent is #41085, fixed by #41086, which put the retry in the
bun_syswrappers.Who can hit it
process.onand the SIGCHLD handler have SA_RESTART (BunProcess.cpp,spawn/process.rs). The SIGINT handlers of the REPL and ofvmwithbreakOnSigintdo not (repl.rs,SigintWatcher.cpp). Native code in the process (an addon,bun:ffi, a preloaded library) can install a handler without it.siginterrupt(SIGUSR1, 1)throughbun:ffi, a storm of SIGUSR1 from a child, 40 copies of a 32 MB file on tmpfs. On 1.4.3-canary (367d939),cpSyncthrows EINTR 40 of 40 times,Bun.write(file, file)2 of 40, andfetchwith aBun.filebody rejects 3 of 40 uploads. On this branch all three are 0 of 40. With SA_RESTART kept, both builds are 0 of 40.truncatebehind a file lease andBun.writebetween FIFOs also return EINTR from a real signal. The other calls need a file system that waits (a network mount, a FUSE daemon).Messages on main
EINTR: interrupted system call, unlink '<path>', and the same withrmdir,truncate,mkdtemp,fsync,fdatasync,link '<from>' -> '<to>'EINTR: interrupted system call, copy_file_range '<dest>'fromfs.cpEINTR: interrupted system call, copy_file_range(orsendfile,splice) fromBun.writeEINTR fetching "<url>"fromfetchcopyFileSyncorcpturns clones off for the rest of the process. The clone rows of the test show it.What changed
src/sys/Error.rs(own commit):Error::get_error_code_tag_namenames an errno that the table does not declareEUNKNOWN. This is the hunk that Remove libuv on Windows #42819 carries.src/sys/lib.rs:check!loop:link,truncate,posix_rmdir,unlink_without_path,copy_file_range,splice,ioctl_ficlonefdatasync(the error carries the fd),mkdtemp(writes theXXXXXXback before it calls again, because glibc leaves its candidate name in the template)sendfiletakes anoffset. macOS and FreeBSD get asendfileof the same shape: EINTR with no bytes sent calls again, and EAGAIN or EINTR after some bytes is a short count. libuv has the same rule (uv__fs_sendfileinsrc/unix/fs.c).exists_zandexists_os_pathbecomeexists_at. Its Linux arm is the rawfaccessat, which retries. Its other arm now loops.lstatatsharesfstatat_with_flags.realpathloops.c::clonefile_rc,c::copyfile_rc, thec::truncatere-export,c::sendfile(macOS, FreeBSD),linux::sendfile,linux_syscall::sendfile,err_with_path.linux::copy_file_rangeandlinux::ioctl_ficloneare private to the crate.src/runtime/node/node_fs.rs: all 21errno_sys*sites andmkdtempcall the wrappers. The trait is deleted.errno_syslines: 32 to 0.src/runtime/webcore/blob/copy_file.rs: the three raw calls ofdo_copy_file_range(copy_file_range, sendfile, splice).src/http/SendFile.rs: one body for Linux, macOS and FreeBSD onbun_sys::sendfile. Before, onlyBun.serveretried, andfetchrejected on all three.src/runtime/server/FileResponseStream.rs,src/sys/copy_file.rs:bun_sys::sendfile.src/jsc/bindings/c-bindings.cpp:is_executable_filecallsstatoropenagain on EINTR.src/sys(unlink, rmdir, link, truncate, mkdtemp, access, fsync, fdatasync, splice): 7 to 1. Uses of the raw thunks outsidesrc/sys: 24 to 0. Source: 10 files, +441/-743.The wrappers that take a path and put none on the error (
link,truncate,posix_rmdir,unlink_without_path) followstatxandlstatx: node:fs reports the path its caller passed, so it boxes that path once, as before. With the path on the wrapper's error it would be boxed twice.fcopyfile
Apple's
copyfile.ccopies from the file positions of both fds and endscopyfile_datawithftruncate(dst_fd, totalCopied), wheretotalCopiedcounts one call. A second call after a partial copy copies the rest and truncates the destination to the length of the rest.bun_sys::fcopyfilehas called again on every EINTR since #41086. It now calls again only while both positions are at 0.bun_sys::copy_fileused its own single call and now uses the wrapper.fetchuploads on macOS and FreeBSDA review found that only the Linux arm of
SendFile::writeused the wrapper. The three arms are now one body onbun_sys::sendfile.sendfilewhen the read of the file is interrupted before it read a byte, or when the wait for the send-buffer lock is interrupted (bsd/kern/uipc_syscalls.c). The read waits on NFS, SMB, FUSE or a dataless file. A local APFS file does not wait. On main the upload then rejects withEINTR fetching "<url>".sys/kern/kern_sendfile.c, no path returns EINTR for the call thatfetchmakes (non-blocking socket, no flags). The FreeBSD arm is a parity change. It is compiled for x86_64-unknown-freebsd and has not run. No CI lane runs FreeBSD tests.Content-Length: 0. fetch: send an empty Bun.file() slice without sendfile and close its file #44896 fixes the same case infetch.rs.EAGAIN fetching "<url>"although every byte is queued. XNU tests the socket space before it tests the count.sendfilewaits for mbufs (Bun.serve: stop using sendfile(2) for file responses on macOS #33728). This PR takes no position on fetch: stop using sendfile(2) for file request bodies on macOS #41905, which removes the macOS call fromfetch.Node
cpSyncover an existing file isstd::filesystem::copy_file(CpSyncOverrideFileinsrc/node_file.cc), not a libuv request.mkdtemp: libuv callsmkdtempagain on the same buffer. After a glibc call that consumed theXXXXXX, the second call answers EINVAL. Bun writes theXXXXXXback. If the first call did create a directory, the second creates another.fsync: libuv issuesF_FULLFSYNC.bun_sys::fsyncissuesfsync(2). Not changed here (node:fs: run appendFile through writeFile's write path and report the { flush: true } fsync error #36485 lists it).Error shape for an errno outside the table (524 through the shim, main to this branch)
fsyncSync,fdatasyncSync,unlinkSync,rmdirSync,linkSync,truncateSync,cpSync,copyFileSync:errno-134 to -524.codestaysEUNKNOWN.bun_syswrappers (accessSync,mkdtempSync, and the rest):codeabsent toEUNKNOWN, messageUnknown Error, xtoEUNKNOWN: unknown error, x.Bun.write(file, file): no change (-134).Error::name()andOutput::errprintEUNKNOWNwhere they printedUNKNOWN.Log::add_sys_errorgains the prefix.bun lint(src/lint/driver/discover.rs:196) reports such a stat error where it read it as "nothing there". The shellcdmessage isunknown error. No change:Listener.rs:376,shell/Builtin.rs:1007.Measurements
Release builds of main 017b243 and of this change on top of it.
perf,straceandvalgrindare not installed here, so gdb single-steps the call from the entry of its host function to its return, after 30 calls. It counts instructions,syscallinstructions and calls of the mimalloc entry points. 5 calls per row, minimum shown.unlinkSyncunlinkSyncENOENTrmdirSyncrmdirSyncENOENTlinkSynclinkSyncEEXISTtruncateSynctruncateSyncENOENTfsyncSyncfsyncSyncEBADFfdatasyncSyncfdatasyncSyncEBADFmkdtempSyncmkdtempSyncENOENTexistsSynchitexistsSyncmissaccessSync(control)copyFileSync64 KiBcpSync64 KiBBun.write(file, file)copy loopBun.write(device, file)copy loopBun.whichhitBun.whichmissfetchupload, oneSendFile::writeunlinkSyncon both).existsSyncissuesfaccessat(2)where it issuedaccess(2).sizeof the release binary, text: 106,738,870 to 106,738,102 bytes.Bun.write,Bun.file().unlink()): 39 of 39 rows print the samemessage,code,errno,syscall,path,destandfdon both builds.Test
A preloaded shim (LD_PRELOAD on Linux, DYLD_INSERT_LIBRARIES on macOS) fails the first call of a libc function with an errno. The directory of a row names the function and the errno. The shim logs each call it fails, and a row reports that log, so a pass cannot come from a shim that did not fire.
existsSyncon Linux: main calls libcaccess, the shim fails it, the answer isfalse. The branch issues the rawfaccessat, which no preloaded library can fail. The row asserts the answer and an empty log.accessSyncis the control that theaccesshook fires. The retry of the raw call islinux_syscall::retry, the same loop asopenandstat.sendfileto 7777 bytes, so thatSendFile::writeruns about 30 times.lstatatandis_executable_fileon macOS, the FICLONE probe ofbun_sys::copy_file,Bun.servefile responses (same wrapper as thefetchrow, and the existing suite).fs-stat-seccomp-linux.test.tsdoes. A compiler that is not in the page cache takes seconds to start, and a test has 5 seconds.Suites run on the debug build of this branch, after the rebase on 25ef693:
fs-eintr-syscalls.test.ts,cp.test.ts,fs-stat-seccomp-linux.test.ts,bun-serve-file.test.ts,fetch-file-upload.test.ts,which.test.ts,bun-file.test.ts,init.test.ts, the 250 nodetest-fs-*files (parallel and sequential) and the 14 nodetest-compile-cache-*files.fs.test.ts(609 pass, 8 fail),bun-write.test.js(105 pass, 1 fail) andglob/scan.test.ts(200 pass, 6 fail): each failure is a time-out of the debug build on this machine. They are the scans of the whole repository and the tests that queue behind them. Thermdir,opendir,createReadStreamandBun.file(0)tests among them pass when run alone.cargo check --workspacepasses for linux gnu and musl, android, darwin x64 and arm64, freebsd and windows.sendfile, the upload rows):fs-eintr-syscalls.test.ts(4 pass, 2 skip),fetch-file-upload.test.ts,cp.test.ts,fs-stat-seccomp-linux.test.tsandbun-serve-file.test.tspass on the debug build.cargo check --workspacepasses for darwin arm64 and freebsd, andcargo check -p bun_sys -p bun_httpfor linux gnu and musl, android, darwin x64 and windows.cpwalk): the same five suites andshell/commands/cp.test.tspass on the debug build, andcargo check --workspacepasses for darwin arm64, freebsd and windows.Not in scope, each still single-shot
getdents64still failsfs.readdir,fs.opendir, recursivefs.rmandfs.cp,fs.globandBun.Glob.close(2): not retried on purpose (sys: one single-shot POSIX close behind close_allowing_standard_io and bun_sys::close #44329, sys, node:fs: close reports every errno except EINTR and EINPROGRESS #44330).tcgetattrandtcsetattr(src/sys/lib.rs): terminal calls. The callers discard the result.bun_sys::c::fchmodre-export: 5 callers drop its result (bun build --compile, the copyfile backend ofbun install).src/bun_core/util.rs:4192,access(X_OK):bun_coreis belowbun_sys.fetchupload: asendfilethat sends nothing and reports EAGAIN fails the request, on Linux, macOS and FreeBSD alike. It is not EINTR and is not changed. fetch: fall back to read+write when sendfile(2) refuses a Bun.file() body #41494 has an arm for it on Linux.exists: only EINTR is fixed. Any other errno of the probe still reads as "missing".copyfile()withCOPYFILE_EXCL: if the first call created the destination and then failed with EINTR outside the data copy, the second call answers EEXIST.disallowed-methodson the libc fs calls, or a source lint) checks where a call is spelled, not whether it retries. It can be a PR of its own if a maintainer wants it.Open pull requests this touches (
git merge-treeagainst main and this branch)node_fs.rs), Honor Bun.file().slice() bounds in Bun.write #41209, Bun.write: copy a file to an O_APPEND destination fd with the read/write loop #41685 (blob/copy_file.rs), Close the connection when a Bun.file response ends short of its Content-Length #41622 (FileResponseStream.rs).link,truncate,posix_rmdirandmkdtemptobun_syswith the same names, documented "no EINTR retry" and with the path on the error. Here they retry and carry no path, andmkdtemptakes the template with its NUL and returnsMaybe<()>. node:fs: remove unsafe from node_fs.rs and node_fs_binding.rs #40212 conflicts with main in 23 regions and with this branch in 37.NodeFS::unlinkandfsyncto the wrappers and has the sameError.rshunk. It conflicts with main in 109 regions and with this branch in 119. errno: keep the kernel's number when a node:fs syscall fails with a code outside the table #40783 has another form of the hunk.node_fs.rsas one helper.fsyncreports no fd, as on main, andfdatasynckeeps its fd.sendfilecall offetchwith a copy loop. It conflicts with main already, and with this branch inSendFile.rs(3 regions) andsys/lib.rs(1). If it lands after this PR, it callsbun_sys::sendfilefor Linux and FreeBSD and deletes the macOS block of the wrapper,shim_sendfileand the macOS upload rows. It must not bringc::sendfileback for its FreeBSD arm: no lane runs FreeBSD tests, so nothing goes red.SendFile::write, which is now the shared body. There is no textual conflict in that file. ItsStatus::Refusedarm needs thecfgof the variant (linux, android) there, and its EAGAIN arm then covers all three systems.sendfile. No conflict. It makes the zero-count guard of the wrapper unreachable fromfetch.src/http) has to resolveSendFile.rs(2 regions) andsys/lib.rs(2) over this branch.Questions for @Jarred-Sumner and @dylan-conway: is the retry right for the four wrappers of #40212, and can the
Error.rshunk of #42819 land here? The first commit holds only that hunk and can move to a PR of its own. One more for @Jarred-Sumner: doesfetchkeepsendfile(2)on macOS (#41905)? If not, the macOS block of the wrapper and its rows go, and the FreeBSD arm and the single body stay.Self-review, rejected
copy_file_inner,copy_single_file_sync). It is a refactor of code that four open PRs rewrite, and Consolidate node fs/path/types helpers #32021 carries it. Both loops now call the same wrapper.splice(it finds the blocked thread in/proc/self/taskand signals it) and one fortruncatebehind a file lease (it needs lease support on the CI file system, and the kernel waits up to 45 s when a step goes wrong). The shim rows forspliceandtruncatepin the same retry.sendfilesends nothing and reports EAGAIN. It is a separate bug, and fetch: fall back to read+write when sendfile(2) refuses a Bun.file() body #41494 is open for its Linux arm. This PR names it above.freebsd-smokeworkflow on a probe branch). Not done. The arm is compiled only, and the description says so.Credits: the
Error.rshunk and the wrapper calls ofunlinkandfsyncare from #42819. The wrapper names are from #40212.