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

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

commit 69112fdb9e1a051b4072f298998f28d4154d96de
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Oct 11 10:46:29 2026 +0200

    libs/libc/stdio: Close the descriptor in fclose() of a standard stream.
    
    fclose() of stdin, stdout or stderr flushed the stream and returned, so
    the file descriptor stayed open.  POSIX says that fclose() closes the
    file descriptor of any stream.  A program that sends its output through
    a pipe and ends it with fclose(stdout) never closed the write end: the
    reader waited for the end of file forever.
    
    Close the file descriptor of the builtin streams as for any other
    stream.  The FILE structures stay in the stream list and are not freed,
    and they keep -1 as the file descriptor, so a later use of the stream
    fails and does not reach a new file with the same descriptor.  freopen()
    of the stream still works.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 libs/libc/stdio/lib_fclose.c | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/libs/libc/stdio/lib_fclose.c b/libs/libc/stdio/lib_fclose.c
index 89e18631895..e36a658497a 100644
--- a/libs/libc/stdio/lib_fclose.c
+++ b/libs/libc/stdio/lib_fclose.c
@@ -108,17 +108,17 @@ int fclose(FAR FILE *stream)
           errcode = get_errno();
         }
 
-      /* Skip close the builtin streams(stdin, stdout and stderr) */
+      /* The builtin streams (stdin, stdout and stderr) stay in the stream
+       * list and are not freed, but their file descriptor is closed as for
+       * any other stream.
+       */
 
-      if (stdstream)
+      if (!stdstream)
         {
-          nxmutex_unlock(&slist->sl_lock);
-          goto done;
-        }
-
-      /* Remove FILE structure from the stream list */
+          /* Remove FILE structure from the stream list */
 
-      sq_rem(&stream->fs_entry, &slist->sl_queue);
+          sq_rem(&stream->fs_entry, &slist->sl_queue);
+        }
 
       nxmutex_unlock(&slist->sl_lock);
 
@@ -152,6 +152,16 @@ int fclose(FAR FILE *stream)
           errcode = get_errno();
         }
 
+      if (stdstream)
+        {
+          /* A later use of the stream fails, and does not reach a file
+           * that gets the same descriptor.
+           */
+
+          stream->fs_cookie = (FAR void *)(intptr_t)-1;
+          goto done;
+        }
+
 #ifndef CONFIG_STDIO_DISABLE_BUFFERING
       /* Destroy the mutex */
 

Reply via email to