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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7be533efd5c fs/poll: Tear down a poll through the file of its setup.
7be533efd5c is described below

commit 7be533efd5cf27cb4187ab652e13fc597111d10b
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Nov 5 11:38:26 2026 +0100

    fs/poll: Tear down a poll through the file of its setup.
    
    poll_teardown() looked up the file again by its descriptor.  If another
    thread closed the descriptor during the poll, the lookup failed, so the
    driver was not told and the reference of the setup was not dropped.  The
    file stayed open, and the driver kept a pointer to the struct pollfd_s,
    which is gone when poll() returns.  The next event of that driver used
    this pointer.
    
    Keep the file of the setup in struct pollfd_s and use it in
    poll_teardown().  The file stays open until poll() ends, and then it
    closes.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 Documentation/os/filesystem/index.rst |  3 ++-
 fs/vfs/fs_poll.c                      | 32 +++++++++++++++-----------------
 include/nuttx/poll.h                  |  5 +++++
 3 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/Documentation/os/filesystem/index.rst 
b/Documentation/os/filesystem/index.rst
index 6979c661e4a..310fd5e4b29 100644
--- a/Documentation/os/filesystem/index.rst
+++ b/Documentation/os/filesystem/index.rst
@@ -248,7 +248,8 @@ belonging to a unified interface:
   ``struct pollfd_s`` (``include/nuttx/poll.h``) is the kernel copy of one
   ``struct pollfd`` entry. It has 32-bit ``events`` and ``revents`` and the
   fields ``arg``, ``cb`` and ``priv`` that the kernel and the driver use.
-  The driver reports events with ``poll_notify()``.
+  ``filep`` is for ``poll()`` itself. The driver reports events with
+  ``poll_notify()``.
 
   :param FAR struct file * filep: Open file's pointer.
   :param FAR struct pollfd_s * fds: The structure describing the events to be
diff --git a/fs/vfs/fs_poll.c b/fs/vfs/fs_poll.c
index 11d369a0d91..50a84ed0769 100644
--- a/fs/vfs/fs_poll.c
+++ b/fs/vfs/fs_poll.c
@@ -86,25 +86,16 @@ static inline void poll_teardown(FAR struct pollfd_s *fds, 
nfds_t nfds,
   *count = 0;
   for (i = 0; i < nfds; i++)
     {
-      if (fds[i].fd >= 0)
-        {
-          FAR struct file *filep;
-          int ret;
-
-          ret = file_get(fds[i].fd, &filep);
-          if (ret >= 0)
-            {
-              ret = file_poll(filep, &fds[i], false);
-
-              /* Calling putfilep twice to ensure reference counting
-               * for filep remains consistent with its state for
-               * before the poll.
-               */
+      /* Use the file of the setup and not the descriptor: another thread
+       * may have closed the descriptor during the poll.
+       */
 
-              file_put(filep);
-              file_put(filep);
-            }
+      if (fds[i].filep != NULL)
+        {
+          int ret = file_poll(fds[i].filep, &fds[i], false);
 
+          file_put(fds[i].filep);
+          fds[i].filep = NULL;
           if (ret < 0)
             {
               fds[i].revents |= POLLERR;
@@ -150,6 +141,7 @@ static inline int poll_setup(FAR struct pollfd_s *fds, 
nfds_t nfds,
       fds[i].cb      = poll_default_cb;
       fds[i].revents = 0;
       fds[i].priv    = NULL;
+      fds[i].filep   = NULL;
 
       /* Check for invalid descriptors. "If the value of fd is less than 0,
        * events shall be ignored, and revents shall be set to 0 in that entry
@@ -167,11 +159,17 @@ static inline int poll_setup(FAR struct pollfd_s *fds, 
nfds_t nfds,
           ret = file_get(fds[i].fd, &filep);
           if (ret >= 0)
             {
+              /* The reference stays until poll_teardown() */
+
               ret = file_poll(filep, &fds[i], true);
               if (ret < 0)
                 {
                   file_put(filep);
                 }
+              else
+                {
+                  fds[i].filep = filep;
+                }
             }
 
           if (ret < 0)
diff --git a/include/nuttx/poll.h b/include/nuttx/poll.h
index cd12a75ab70..e5f75357e34 100644
--- a/include/nuttx/poll.h
+++ b/include/nuttx/poll.h
@@ -54,6 +54,7 @@ typedef uint32_t pollevent_t;
 
 /* The poll callback type */
 
+struct file;
 struct pollfd_s;
 typedef CODE void (*pollcb_t)(FAR struct pollfd_s *fds);
 
@@ -69,6 +70,10 @@ struct pollfd_s
   FAR void    *arg;     /* The poll callback function argument */
   pollcb_t     cb;      /* The poll callback function */
   FAR void    *priv;    /* For use by drivers */
+
+  /* The file of the setup, for poll() itself */
+
+  FAR struct file *filep;
 };
 
 /****************************************************************************

Reply via email to