Skip to content

Bun.write: fall back to read/write when copy_file_range fails with EBADF on an O_APPEND destination - #46636

Open
back2dos wants to merge 1 commit into
oven-sh:mainfrom
back2dos:bun-write-append-fd-ebadf
Open

back2dos wants to merge 1 commit into
oven-sh:mainfrom
back2dos:bun-write-append-fd-ebadf

Conversation

@back2dos

Copy link
Copy Markdown

What does this PR do?

Bun.write(Bun.stdout, Bun.file(path)) goes through copy_file_range(2) on Linux. That call fails with EBADF when the destination was opened with O_APPEND, which is what >> does to stdout. do_copy_file_range only handled EINVAL (and clears O_APPEND there), so the write rejected:

bun -e 'await Bun.write(Bun.stdout, Bun.file("/etc/hostname"))' >> /tmp/x
# bun 1.4.4: EBADF: bad file descriptor, copy_file_range (exit code 1)

When the first call fails with EBADF, this now falls back to the read/write loop, which appends as expected, and a destination that really is a bad fd still fails there with its own error.

How did you verify your code works?

  • Added a test to test/js/bun/io/bun-write.test.js that runs the command above with >> and checks the output and the file.
  • With bun 1.4.4 the test fails with the EBADF error.
  • I could not build Bun locally (no Rust toolchain on this machine), so I have not run bun bd test on this change, and the Rust is uncompiled.

🤖 Generated with Claude Code

…ADF on an O_APPEND destination

copy_file_range(2) returns EBADF for an O_APPEND destination; only EINVAL was handled.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

@claude claude Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@coderabbitai

coderabbitai Bot commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Source mode: Auto
  • Repository: oven-sh/bun
  • Branch: main
  • File: .coderabbit.yaml
  • Commit: 5c6d4e2
  • Layers: Repository YAML
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 97b7783d-d0e1-4392-8e6f-fee2ef8f7415
📥 Commits

Reviewing files that changed from the base of the PR and between 5c6d4e2 and 59db5c3.

📒 Files selected for processing: 2
  • src/runtime/webcore/blob/copy_file.rs
  • test/js/bun/io/bun-write.test.js

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 2 remain after this review.

Walkthrough

On Linux and Android, CopyFile::do_copy_file_range falls back to read/write when a copy syscall returns EBADF before copying any bytes. A POSIX-only test covers Bun.write to stdout redirected in append mode.

Changes

Append-mode file copy

Layer / File(s) Summary
EBADF fallback and append-mode coverage
src/runtime/webcore/blob/copy_file.rs, test/js/bun/io/bun-write.test.js
CopyFile::do_copy_file_range uses the read/write fallback when EBADF occurs before any bytes are copied. The test checks the reported byte count, appended file contents, empty stdout, and successful exit.

Suggested reviewers: jarred-sumner

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 59db5

No actionable issue was established that would prevent merging after normal checks.

Pre-merge checks: Passed 4
Check name Status Explanation
Title check Passed The title clearly and concisely describes the main change: falling back to read/write when copy_file_range returns EBADF for an O_APPEND destination.
Description check Passed The description includes both required sections. It explains the change, failure mode, test coverage, and verification limits. It also states that the Rust code was not compiled locally.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@robobun

robobun commented Oct 24, 2026

Copy link
Copy Markdown
Collaborator

Thank you for this change. #41685 is an older pull request for the same EBADF, and it now uses your fallback after the failed copy_file_range, with you as co-author of the commit. It differs in two points: the fallback runs only when the destination is writable and has O_APPEND (measured on a build of this arm, a read-only destination fd reads up to 64 KiB of the source before write fails), and it removes the code that clears O_APPEND on a terminal. Its description says Supersedes #46636, so this pull request closes if that one merges. A maintainer can decide which of the two pull requests to keep.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants