This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git


The following commit(s) were added to refs/heads/master by this push:
     new ed063a098 nshlib: fix infinite loop on broken stdout in nsh_catfile
ed063a098 is described below

commit ed063a0981f97949c1294745eb5602bfa8170d36
Author: wangjianyu3 <[email protected]>
AuthorDate: Tue May 19 16:42:47 2026 +0800

    nshlib: fix infinite loop on broken stdout in nsh_catfile
    
    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 <[email protected]>
---
 nshlib/nsh_console.c | 23 ++++++++++++-----------
 nshlib/nsh_fsutils.c |  9 ++++++++-
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/nshlib/nsh_console.c b/nshlib/nsh_console.c
index ebcbe6fb2..0e4284222 100644
--- a/nshlib/nsh_console.c
+++ b/nshlib/nsh_console.c
@@ -131,18 +131,19 @@ static ssize_t nsh_consolewrite(FAR struct nsh_vtbl_s 
*vtbl,
                                 FAR const void *buffer, size_t nbytes)
 {
   FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl;
-  ssize_t ret;
-
-  /* Write the data to the output stream */
 
-  ret = write(OUTFD(pstate), buffer, nbytes);
-  if (ret < 0)
-    {
-      _err("ERROR: [%d] Failed to send buffer: %d\n",
-          OUTFD(pstate), errno);
-    }
-
-  return ret;
+  /* Write the data to the output stream.
+   *
+   * Errors are reported to the caller via the negative return value and
+   * errno; do NOT _err() here.  OUTFD may itself be wired to the syslog
+   * backend (e.g. nsh_catfile dumping /dev/log on dmesg), in which case
+   * logging on write failure would produce new bytes, get picked up by
+   * the next read(), and lock the shell into an infinite loop at the
+   * highest priority — independent of which errno (EPIPE/EIO/ENOSPC/...)
+   * the underlying device returns.
+   */
+
+  return write(OUTFD(pstate), buffer, nbytes);
 }
 
 /****************************************************************************
diff --git a/nshlib/nsh_fsutils.c b/nshlib/nsh_fsutils.c
index 878c1d18e..7044d8d54 100644
--- a/nshlib/nsh_fsutils.c
+++ b/nshlib/nsh_fsutils.c
@@ -228,8 +228,14 @@ int nsh_catfile(FAR struct nsh_vtbl_s *vtbl, FAR const 
char *cmd,
                                  NSH_ERRNO_OF(errcode));
                     }
 
+                  /* Jump straight to cleanup.  On a broken stdout (e.g.
+                   * closed PTY master) we must not keep reading: the
+                   * outer loop would otherwise drain /dev/log forever
+                   * when cat is dumping it on dmesg.
+                   */
+
                   ret = ERROR;
-                  break;
+                  goto errout;
                 }
               else
                 {
@@ -255,6 +261,7 @@ int nsh_catfile(FAR struct nsh_vtbl_s *vtbl, FAR const char 
*cmd,
 
   /* Close the input file and return the result */
 
+errout:
   close(fd);
   free(buffer);
   return ret;

Reply via email to