Title: diff panics (broken-pipe unwrap) when its stdout is closed early · Issue #244 · uutils/diffutils · GitHub
Open Graph Title: diff panics (broken-pipe unwrap) when its stdout is closed early · Issue #244 · uutils/diffutils
X Title: diff panics (broken-pipe unwrap) when its stdout is closed early · Issue #244 · uutils/diffutils
Description: Summary When diff's standard output is a pipe whose reader closes early (e.g. diff … | head), uutils diff aborts with a panic (exit 134, core dump) instead of dying cleanly to SIGPIPE like GNU (exit 141). The output is written with a bar...
Open Graph Description: Summary When diff's standard output is a pipe whose reader closes early (e.g. diff … | head), uutils diff aborts with a panic (exit 134, core dump) instead of dying cleanly to SIGPIPE like GNU (exi...
X Description: Summary When diff's standard output is a pipe whose reader closes early (e.g. diff … | head), uutils diff aborts with a panic (exit 134, core dump) instead of dying cleanly to SIGPIPE like GNU ...
Opengraph URL: https://github.com/uutils/diffutils/issues/244
X: @github
Domain: redirect.github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"diff panics (broken-pipe unwrap) when its stdout is closed early","articleBody":"## Summary\n\nWhen `diff`'s standard output is a pipe whose reader closes early (e.g. `diff … | head`), uutils `diff` aborts with a panic (exit 134, core dump)\ninstead of dying cleanly to `SIGPIPE` like GNU (exit 141). The output is written with a bare `.unwrap()` on the `write_all`/`push_output` result; the `BrokenPipe` error is unwrapped and, under `panic=\"abort\"`, aborts the process. This affects every output mode: the normal/context/unified/ed path writes the buffered result in `src/diff.rs:94`, and the side-by-side (`-y`) path writes each line in `src/side_diff.rs:353-356`.\n\n## Steps to reproduce\n\n```console\n$ seq 1 100000 \u003e b1; seq 1 100000 | sed 's/5/X/' \u003e b2\n$ diffutils diff b1 b2 | head -1\nthread 'main' panicked at src/diff.rs:94:41:\ncalled `Result::unwrap()` on an `Err` value: Os { code: 32, kind: BrokenPipe, message: \"Broken pipe\" }\n$ echo \"${PIPESTATUS[0]}\"\n134\n```\n\nSide-by-side mode hits the sibling site `src/side_diff.rs:353`:\n\n```console\n$ diffutils diff -y b1 b2 | head -1\nthread 'main' panicked at src/side_diff.rs:353:87:\ncalled `Result::unwrap()` on an `Err` value: Os { code: 32, kind: BrokenPipe, message: \"Broken pipe\" }\n$ echo \"${PIPESTATUS[0]}\"\n134\n```\n\n## Expected behavior\n\nMatch GNU: a closed output pipe terminates the program via `SIGPIPE` (exit 141) with no error message and no core dump.\n\n```console\n$ /usr/bin/diff b1 b2 | head -1\n1c1\n$ echo \"${PIPESTATUS[0]}\"\n141\n$ /usr/bin/diff -y b1 b2 | head -1\n1 \u003c 1\n$ echo \"${PIPESTATUS[0]}\"\n141\n```\n\n## Root cause\n\nThe full diff output (normal/context/unified/ed) is buffered and written once:\n\n```rust\n// src/diff.rs:94\nio::stdout().write_all(\u0026result).unwrap();\n```\n\nSide-by-side writes each line straight to the locked stdout and unwraps every\nwrite:\n\n```rust\n// src/side_diff.rs:353-356\npush_output(...).unwrap(); // and the sibling unwraps at :354, :356\n```\n\nAny `write_all`/`push_output` error — `BrokenPipe` in the common pipe-closed case — is unwrapped and aborts. \n\n_Found by our static analysis tooling._","author":{"url":"https://github.com/leeewee","@type":"Person","name":"leeewee"},"datePublished":"2026-06-10T04:50:40.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/244/diffutils/issues/244"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:2f7ac55f-93d9-2917-d213-4fa386e9b4cb |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 9550:1C4EB2:BA8451:F80241:6A4D46D2 |
| html-safe-nonce | 75029b88cdbcc6955d4d24aacba0017802dc406076377674b83f11fff44eca2c |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5NTUwOjFDNEVCMjpCQTg0NTE6RjgwMjQxOjZBNEQ0NkQyIiwidmlzaXRvcl9pZCI6IjY5NzkzOTE0NjIwMjM0NDgyNzQiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | f62a106be3abb2f9cc3c808cb12360e7f3a3b5c0479f3df36feaa866d02cc91a |
| hovercard-subject-tag | issue:4628095723 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/uutils/diffutils/244/issue_layout |
| twitter:image | https://opengraph.githubassets.com/df627d59ebf41c483b4f1cbc8e62b86e66de492ab1e0e7c785c824812c15b0f9/uutils/diffutils/issues/244 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/df627d59ebf41c483b4f1cbc8e62b86e66de492ab1e0e7c785c824812c15b0f9/uutils/diffutils/issues/244 |
| og:image:alt | Summary When diff's standard output is a pipe whose reader closes early (e.g. diff … | head), uutils diff aborts with a panic (exit 134, core dump) instead of dying cleanly to SIGPIPE like GNU (exi... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | leeewee |
| hostname | github.com |
| expected-hostname | github.com |
| None | 92571a8944142227b7e19cd10918b1ddd06e5066c1ad5bc7e4769cf6140a87e6 |
| turbo-cache-control | no-preview |
| go-import | github.com/uutils/diffutils git https://github.com/uutils/diffutils.git |
| octolytics-dimension-user_id | 5148717 |
| octolytics-dimension-user_login | uutils |
| octolytics-dimension-repository_id | 341787720 |
| octolytics-dimension-repository_nwo | uutils/diffutils |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 341787720 |
| octolytics-dimension-repository_network_root_nwo | uutils/diffutils |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 56fc8347865a14e2ec811533d68f929cf4e0ec19 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width