Skip to content

split: retry short writes in custom_write so the input tail is not silently dropped - #15874

Open
mavrodikomsd-eng wants to merge 1 commit into
uutils:mainfrom
mavrodikomsd-eng:split-write-all-short-writes
Open

mavrodikomsd-eng wants to merge 1 commit into
uutils:mainfrom
mavrodikomsd-eng:split-write-all-short-writes

Conversation

@mavrodikomsd-eng

Copy link
Copy Markdown

Fixes #15820

custom_write() used a single Write::write() call, so a short write (e.g. the output volume filling up mid-write or a file size limit being hit) silently dropped the rest of the buffer: ByteChunkWriter broke out of its loop on the short count and LineChunkWriter ignored the count entirely. In the worst case the last chunk of split -b/split -l came out truncated with exit code 0, while GNU split reports the write error.

The write loop now keeps going until all bytes are accepted; the next write() call surfaces the underlying error, so a full volume or ulimit -f limit results in a proper error exit like GNU. The --filter BrokenPipe handling is preserved: it still counts as a full write.

Testing: added unit tests around the new write_repeating() helper with mock writers covering short writes, a filling device, BrokenPipe (ignored and not ignored) and zero-progress writes. The 4 pre-existing test_split_number_* failures on Windows are unchanged (they also fail on current main without this patch).

…lently dropped

A single write() may accept only part of the data when the output volume
fills up or a file size limit is reached. ByteChunkWriter then broke out
of its loop on the short count and LineChunkWriter ignored the count
entirely, so the last chunk could end up truncated with exit code 0.
GNU split reports the write error instead.

custom_write now keeps writing until all bytes are accepted; the next
write() call surfaces the underlying error. BrokenPipe handling for
--filter is unchanged.

Fixes uutils#15820
@codspeed

codspeed Bot commented Oct 27, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 12.65%

2 warnings

⚠️ 5 benchmarks are dominated by system calls

System calls cannot be simulated consistently and are left out of the measure. The reported value understates the real cost. Switch to the Walltime instrument to measure them.

Learn more about system calls

See affected benchmarks

⚠️ Base and head ran on different runner types

Some benchmarks with significant performance changes were compared across different runner types, so the changes might not come from the code. Run base and head on the same runner type, or use CodSpeed Macro Runners for more stable results.

Learn more about Macro Runners

Open the report in CodSpeed to investigate

❌ 3 regressed benchmarks
✅ 7 untouched benchmarks
⏩ 462 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ CPU Simulation split_lines 8.5 ms 10.3 ms -17.14%
❌ CPU Simulation split_numeric_suffix 8.7 ms 10.5 ms -16.8%
❌ CPU Simulation split_bytes 696.2 µs 720.3 µs -3.35%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing mavrodikomsd-eng:split-write-all-short-writes (325f772) with main (c1f1728)2

Open in CodSpeed

Footnotes

  1. 462 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

  2. No successful run was found on main (ca5c757) during the generation of this report, so c1f1728 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report. ↩

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.

split: -b and -l ignore short writes, exit 0 with a truncated last chunk

1 participant