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.git

commit 41f29b32e93c8c0463c0af1ede50d5a647cf487b
Author: Xiang Xiao <[email protected]>
AuthorDate: Fri Sep 11 02:22:26 2026 +0800

    libc/aio: loop in aio_suspend() until a listed request completes
    
    aio_suspend() checked the completion status once and then performed a
    single sigtimedwait().  Any SIGPOLL delivered by an unrelated AIO
    operation (one not referenced by 'list') woke the caller even though
    none of the awaited requests had completed, and with a timeout the
    remaining wait time was not preserved either.
    
    Re-check the completion status after every wakeup and continue
    waiting, recomputing the remaining time from the absolute deadline so
    that the full timeout is honored.
    
    Signed-off-by: wushenhui <[email protected]>
---
 libs/libc/aio/aio_suspend.c | 64 +++++++++++++++++++++++++++++++--------------
 1 file changed, 44 insertions(+), 20 deletions(-)

diff --git a/libs/libc/aio/aio_suspend.c b/libs/libc/aio/aio_suspend.c
index d15b546f140..9b3d8f0e6c9 100644
--- a/libs/libc/aio/aio_suspend.c
+++ b/libs/libc/aio/aio_suspend.c
@@ -86,41 +86,65 @@
 int aio_suspend(FAR const struct aiocb * const list[], int nent,
                 FAR const struct timespec *timeout)
 {
+  struct timespec end;
+  struct timespec rem;
   sigset_t set;
   int ret;
   int i;
 
   DEBUGASSERT(list);
 
-  /* Check each entry in the list.  Break out of the loop if any entry
-   * has completed.
-   */
+  if (timeout)
+    {
+      clock_gettime(CLOCK_MONOTONIC, &end);
+      clock_timespec_add(&end, timeout, &end);
+      timeout = &rem;
+    }
+
+  sigemptyset(&set);
+  sigaddset(&set, SIGPOLL);
 
-  for (i = 0; i < nent; i++)
+  for (; ; )
     {
-      /* Check if the I/O has completed */
+      /* Check each entry in the list.  Break out of the loop if any entry
+       * has completed.
+       */
 
-      if (list[i] && list[i]->aio_result != -EINPROGRESS)
+      for (i = 0; i < nent; i++)
         {
-          /* Yes, return success */
+          /* Check if the I/O has completed */
+
+          if (list[i] && list[i]->aio_result != -EINPROGRESS)
+            {
+              /* Yes, return success */
 
-          return OK;
+              return OK;
+            }
         }
-    }
 
-  /* Then wait for SIGPOLL.  On success sigtimedwait() will return the
-   * signal number that cause the error (SIGPOLL).  It will set errno
-   * appropriately for this function on errors.
-   *
-   * NOTE: If completion of the I/O causes other signals to be generated
-   * first, then this will wake up and return EINTR instead of success.
-   */
+      /* Then wait for SIGPOLL.  On success sigtimedwait() will return the
+       * signal number that cause the error (SIGPOLL).  It will set errno
+       * appropriately for this function on errors.
+       *
+       * NOTE: If completion of the I/O causes other signals to be generated
+       * first, then this will wake up and return EINTR instead of success.
+       */
 
-  sigemptyset(&set);
-  sigaddset(&set, SIGPOLL);
+      if (timeout)
+        {
+          clock_gettime(CLOCK_MONOTONIC, &rem);
+          clock_timespec_subtract(&end, &rem, &rem);
+        }
+
+      ret = sigtimedwait(&set, NULL, timeout);
+
+      if (ret < 0)
+        {
+          return ERROR;
+        }
+    }
 
-  ret = sigtimedwait(&set, NULL, timeout);
-  return ret >= 0 ? OK : ERROR;
+  return OK;
 }
 
 #endif /* CONFIG_FS_AIO */

Reply via email to