nshlib: fix infinite loop on broken stdout in nsh_catfile#3496
Open
JianyuWang0623 wants to merge 1 commit into
Open
nshlib: fix infinite loop on broken stdout in nsh_catfile#3496JianyuWang0623 wants to merge 1 commit into
JianyuWang0623 wants to merge 1 commit into
Conversation
When stdout is broken (e.g. PTY master closed), nsh_catfile could spin forever: write() fails, error logging generates syslog output to /dev/log, next read() picks it up, write() fails again, ad infinitum. Two fixes: - nsh_console: drop the _err() in nsh_consolewrite entirely. The risk is errno-agnostic (EPIPE / EIO / ENOSPC / ...): any failure logged here can be re-injected by the syslog backend when OUTFD is bound to /dev/log. Callers already see the failure via the negative return value and errno, so on-failure logging at this layer is redundant. - nsh_fsutils: jump straight from the inner write-failure path to a single errout: cleanup label instead of using a two-level break + flag check, so a failed write cannot fall through to another read(). Assisted-by: GitHubCopilot:claude-4.7-opus Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
xiaoxiang781216
approved these changes
May 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes an infinite loop in
nsh_catfile(used bycat/dmesg) when stdout is broken — for example when a PTY master is closed while the shell is dumping/dev/log.Failure mode:
nsh_catfilereads a chunk from the input file (e.g./dev/log).nsh_consolewritecallswrite(OUTFD, ...), which fails (EPIPE/EIO/ENOSPC/…)._err(), which the syslog backend turned into more bytes on/dev/log.nsh_catfileignored the write error and looped back toread(), picking up the bytes that step 3 just produced.Two independent fixes, either of which would break the loop, both applied for defense in depth:
nshlib/nsh_console.c: drop the_err()innsh_consolewriteentirely. The hazard is errno-agnostic: any logging at this layer can be re-injected whenOUTFDis bound to the syslog backend. Callers already get the failure via the negative return value anderrno, so on-failure logging here is redundant.nshlib/nsh_fsutils.c: on inner-loop write failure innsh_catfile, jump straight to a singleerrout:cleanup label instead of using a two-levelbreakand falling through to anotherread(). A failed write can no longer be followed by another read of the same fd.Impact
cat /dev/log,dmesg, and similar commands now exit cleanly withERRORwhen stdout is broken, instead of hanging the shell. No change on the success path or for non-syslog outputs.nsh_consolewriteare no longer logged at this layer. The information is still available to callers through the return value anderrno, and other layers (e.g. command implementations) remain free to report errors as appropriate.Testing
Regression checks on the happy path:
cat <regular file>— unchanged output, exit status 0.dmesgto a healthy console — unchanged output.catof a non-existent / unreadable file — still reports the original error via the existingnsh_error()paths in callers; no behavioral change beyond the dropped_err()line innsh_consolewrite.