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;
+}