Skip to content

head: distinguish read and write errors in copy loop#12265

Open
gabrielhnf wants to merge 3 commits into
uutils:mainfrom
gabrielhnf:fix-head-read-error-message
Open

head: distinguish read and write errors in copy loop#12265
gabrielhnf wants to merge 3 commits into
uutils:mainfrom
gabrielhnf:fix-head-read-error-message

Conversation

@gabrielhnf
Copy link
Copy Markdown

@gabrielhnf gabrielhnf commented May 12, 2026

Fixes #12234

Problem

When running head on a file that fails during reading (e.g. /proc/self/mem), uutils was reporting:

head: error writing 'standard output': Input/output error

Instead of the correct:

head: error reading '/proc/self/mem': Input/output error

Cause

io::copy merges read and write errors into a single return value with no way to distinguish them. Since all errors were mapped through wrap_in_stdout_error, a read failure was incorrectly attributed to stdout.

Fix

Replaced io::copy with a manual read/write loop and introduced a PrintError enum to tag errors at the source as either ReadError or WriteError. This distinction is preserved all the way up to uu_head, where read errors get the filename attached and write errors are reported against stdout.

Note

  • print_n_bytes has the same issue via send_n_bytes. Fixing it would require introducing a similar distinction inside that function, which felt out of scope for this PR and thus was left for a separate issue.

  • Some code paths in print_but_last_n_bytes, print_but_last_n_lines, and the seekable file path in head_backwards_on_seekable_file still map all errors to PrintError::WriteError as a pragmatic compromise. These paths do not exhibit the bug reported in this issue. Left for a separate issue.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 12, 2026

GNU testsuite comparison:

Skip an intermittent issue tests/tail/retry (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/tail-n0f (fails in this run but passes in the 'main' branch)
Note: The gnu test tests/unexpand/bounded-memory is now being skipped but was previously passing.
Congrats! The gnu test tests/printf/printf-surprise is now passing!

@gabrielhnf gabrielhnf force-pushed the fix-head-read-error-message branch from d05aa2c to f525520 Compare May 12, 2026 23:30
@oech3
Copy link
Copy Markdown
Contributor

oech3 commented May 12, 2026

Err in 1st splice at send_n_bytes is discarded by fallback. So ti should not appear.

Oh Ok. I should split last loop.

@oech3
Copy link
Copy Markdown
Contributor

oech3 commented May 13, 2026

CI's log is not useful form me to investivage what utils is missing import. How did you determine the probrematic commit?

@oech3
Copy link
Copy Markdown
Contributor

oech3 commented May 13, 2026

main is passing OpenBSD CI. So it looks network error.

@gabrielhnf
Copy link
Copy Markdown
Author

Noticed rustix missing in the logs and connected it to the commit since it was the most recent merge introducing that dependency. If main is passing then you're right, likely a transient network error. Sorry for getting ahead of myself.

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.

head /proc/self/mem shows wrong message

2 participants