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 114f7c7d3 testing/ostest: Add a test of close() during poll().
114f7c7d3 is described below

commit 114f7c7d35eb90e280e53fb21e9cc5b593a25517
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Nov 5 12:14:35 2026 +0100

    testing/ostest: Add a test of close() during poll().
    
    Another thread closes the read end of a pipe while the main thread is in
    poll() on it.  When poll() ends the read end must be gone, so the write
    end reports POLLERR, and no driver may keep a pointer to the entry of
    that poll().
    
    Option TESTING_OSTEST_POLL_CLOSE selects the test.  It is on unless
    DEFAULT_SMALL is set.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 testing/ostest/CMakeLists.txt |   4 ++
 testing/ostest/Kconfig        |   8 ++++
 testing/ostest/Makefile       |   4 ++
 testing/ostest/ostest.h       |   4 ++
 testing/ostest/ostest_main.c  |   6 +++
 testing/ostest/poll_close.c   | 107 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 133 insertions(+)

diff --git a/testing/ostest/CMakeLists.txt b/testing/ostest/CMakeLists.txt
index 0580c86a0..387137bd5 100644
--- a/testing/ostest/CMakeLists.txt
+++ b/testing/ostest/CMakeLists.txt
@@ -24,6 +24,10 @@ if(CONFIG_TESTING_OSTEST)
 
   set(SRCS getopt.c libc_memmem.c libc_strto.c restart.c sighelper.c)
 
+  if(CONFIG_TESTING_OSTEST_POLL_CLOSE)
+    list(APPEND SRCS poll_close.c)
+  endif()
+
   if(CONFIG_ENABLE_ALL_SIGNALS)
     list(APPEND SRCS sighand.c signest.c)
   endif()
diff --git a/testing/ostest/Kconfig b/testing/ostest/Kconfig
index ee0c32583..bb9fedd48 100644
--- a/testing/ostest/Kconfig
+++ b/testing/ostest/Kconfig
@@ -153,6 +153,14 @@ config TESTING_OSTEST_MULTIUSER
                CONFIG_LIBC_PASSWD_FILEPATH (default /tmp/ostest_passwd when 
this
                option is enabled).
 
+config TESTING_OSTEST_POLL_CLOSE
+       bool "close during poll test"
+       default !DEFAULT_SMALL
+       depends on PIPES && !DISABLE_PTHREAD
+       ---help---
+               Test that close() of a descriptor while another thread is in 
poll()
+               on it leaves nothing behind.
+
 config TESTING_OSTEST_PTHREAD_SIGQUEUE
        bool "pthread_sigqueue test"
        default !DEFAULT_SMALL
diff --git a/testing/ostest/Makefile b/testing/ostest/Makefile
index 9574f4774..cee89fc9e 100644
--- a/testing/ostest/Makefile
+++ b/testing/ostest/Makefile
@@ -33,6 +33,10 @@ MODULE = $(CONFIG_TESTING_OSTEST)
 
 CSRCS  = getopt.c libc_memmem.c libc_strto.c restart.c sighelper.c
 
+ifeq ($(CONFIG_TESTING_OSTEST_POLL_CLOSE),y)
+CSRCS += poll_close.c
+endif
+
 ifeq ($(CONFIG_ENABLE_ALL_SIGNALS),y)
 CSRCS += sighand.c signest.c
 endif
diff --git a/testing/ostest/ostest.h b/testing/ostest/ostest.h
index a23c95eb8..0ecf7fb83 100644
--- a/testing/ostest/ostest.h
+++ b/testing/ostest/ostest.h
@@ -101,6 +101,10 @@ int memmem_test(void);
 
 int strto_test(void);
 
+/* poll_close.c *************************************************************/
+
+int poll_close_test(void);
+
 /* setvbuf.c ****************************************************************/
 
 #ifndef CONFIG_STDIO_DISABLE_BUFFERING
diff --git a/testing/ostest/ostest_main.c b/testing/ostest/ostest_main.c
index f84e975ad..963c6d284 100644
--- a/testing/ostest/ostest_main.c
+++ b/testing/ostest/ostest_main.c
@@ -288,6 +288,12 @@ static int user_main(int argc, char *argv[])
 
   /* Test misc libc functions. */
 
+#ifdef CONFIG_TESTING_OSTEST_POLL_CLOSE
+  printf("\nuser_main: close during poll test\n");
+  poll_close_test();
+  check_test_memory_usage();
+#endif
+
   printf("\nuser_main: libc tests\n");
   memmem_test();
   strto_test();
diff --git a/testing/ostest/poll_close.c b/testing/ostest/poll_close.c
new file mode 100644
index 000000000..e1c731687
--- /dev/null
+++ b/testing/ostest/poll_close.c
@@ -0,0 +1,107 @@
+/****************************************************************************
+ * apps/testing/ostest/poll_close.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "ostest.h"
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/* Close the descriptor while the main thread is in poll() on it */
+
+static FAR void *close_thread(FAR void *arg)
+{
+  usleep(100000);
+  close((int)(intptr_t)arg);
+  return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: poll_close_test
+ *
+ * Description:
+ *   Another thread closes the read end of a pipe during poll().  When
+ *   poll() ends the read end must be gone, so the write end reports POLLERR,
+ *   and no driver may keep a pointer to the entry of that poll().
+ *
+ ****************************************************************************/
+
+int poll_close_test(void)
+{
+  struct pollfd pfd;
+  pthread_t thread;
+  int fd[2];
+  int ret;
+
+  ret = pipe(fd);
+  if (ret < 0)
+    {
+      printf("poll_close_test: ERROR: pipe failed: %d\n", errno);
+      ASSERT(false);
+    }
+
+  ret = pthread_create(&thread, NULL, close_thread,
+                       (FAR void *)(intptr_t)fd[0]);
+  if (ret != 0)
+    {
+      printf("poll_close_test: ERROR: pthread_create failed: %d\n", ret);
+      ASSERT(false);
+    }
+
+  pfd.fd      = fd[0];
+  pfd.events  = POLLIN;
+  pfd.revents = 0;
+  poll(&pfd, 1, 300);
+  pthread_join(thread, NULL);
+
+  pfd.fd      = fd[1];
+  pfd.events  = POLLOUT;
+  pfd.revents = 0;
+  ret = poll(&pfd, 1, 0);
+  if (ret != 1 || (pfd.revents & POLLERR) == 0)
+    {
+      printf("poll_close_test: ERROR: poll of the writer: %d revents %x\n",
+             ret, pfd.revents);
+      ASSERT(false);
+    }
+
+  close(fd[1]);
+  printf("poll_close_test: PASS\n");
+  return 0;
+}

Reply via email to