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-apps.git
The following commit(s) were added to refs/heads/master by this push:
new 09a59b9c8 testing/ostest: Add pthread_sigqueue test
09a59b9c8 is described below
commit 09a59b9c8bee163ec2f75cd55789233f11bce074
Author: Swatantra Yadav <[email protected]>
AuthorDate: Sun Nov 1 16:53:54 2026 +0530
testing/ostest: Add pthread_sigqueue test
Add automated unit test for pthread_sigqueue() in ostest to verify
signal and payload delivery to a target pthread. Tests error handling
for invalid signal numbers and non-existent thread IDs, as well as
successful signal dispatch and reception with SA_SIGINFO and SI_QUEUE.
Now that pthread_sigqueue() is implemented as a system call
(apache/nuttx#21070), the test runs across flat, protected, and
kernel builds.
Configurable via CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE, enabled by
default for non-small builds (!DEFAULT_SMALL) and gated by
ENABLE_ALL_SIGNALS and !DISABLE_PTHREAD. Progress output and error
messages are streamlined to minimize the flash footprint.
Signed-off-by: Swatantra Yadav <[email protected]>
---
testing/ostest/CMakeLists.txt | 4 +
testing/ostest/Kconfig | 8 ++
testing/ostest/Makefile | 3 +
testing/ostest/ostest.h | 6 +
testing/ostest/ostest_main.c | 8 ++
testing/ostest/pthread_sigqueue.c | 277 ++++++++++++++++++++++++++++++++++++++
6 files changed, 306 insertions(+)
diff --git a/testing/ostest/CMakeLists.txt b/testing/ostest/CMakeLists.txt
index fdcc9e187..0580c86a0 100644
--- a/testing/ostest/CMakeLists.txt
+++ b/testing/ostest/CMakeLists.txt
@@ -93,6 +93,10 @@ if(CONFIG_TESTING_OSTEST)
list(APPEND SRCS timedwait.c pthread_rwlock.c pthread_rwlock_cancel.c
schedlock.c)
+ if(CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE)
+ list(APPEND SRCS pthread_sigqueue.c)
+ endif()
+
if(CONFIG_SCHED_WAITPID)
list(APPEND SRCS pthread_exit.c)
endif()
diff --git a/testing/ostest/Kconfig b/testing/ostest/Kconfig
index d9c9af48a..ee0c32583 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_PTHREAD_SIGQUEUE
+ bool "pthread_sigqueue test"
+ default !DEFAULT_SMALL
+ depends on ENABLE_ALL_SIGNALS && !DISABLE_PTHREAD
+ ---help---
+ Enable automated unit test for pthread_sigqueue() in ostest to
+ verify signal and payload delivery to a target pthread.
+
config TESTING_LOOP_SCALE
int "Loop scale of spinlock test (N x 10,000)"
default 5 if MM_KASAN
diff --git a/testing/ostest/Makefile b/testing/ostest/Makefile
index ba2883025..9574f4774 100644
--- a/testing/ostest/Makefile
+++ b/testing/ostest/Makefile
@@ -99,6 +99,9 @@ endif
ifneq ($(CONFIG_DISABLE_PTHREAD),y)
CSRCS += cancel.c cond.c mutex.c timedmutex.c sem.c semtimed.c barrier.c
CSRCS += timedwait.c pthread_rwlock.c pthread_rwlock_cancel.c schedlock.c
+ifeq ($(CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE),y)
+CSRCS += pthread_sigqueue.c
+endif
ifeq ($(CONFIG_SCHED_WAITPID),y)
CSRCS += pthread_exit.c
diff --git a/testing/ostest/ostest.h b/testing/ostest/ostest.h
index 130dacd72..a23c95eb8 100644
--- a/testing/ostest/ostest.h
+++ b/testing/ostest/ostest.h
@@ -288,6 +288,12 @@ void pthread_exit_test(void);
void pthread_cleanup_test(void);
+/* pthread_sigqueue.c *******************************************************/
+
+#ifdef CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE
+void pthread_sigqueue_test(void);
+#endif
+
/* barrier.c ****************************************************************/
void barrier_test(void);
diff --git a/testing/ostest/ostest_main.c b/testing/ostest/ostest_main.c
index a0b42a67f..f84e975ad 100644
--- a/testing/ostest/ostest_main.c
+++ b/testing/ostest/ostest_main.c
@@ -554,6 +554,14 @@ static int user_main(int argc, char *argv[])
check_test_memory_usage();
#endif
+#ifdef CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE
+ /* Verify pthread_sigqueue interface */
+
+ printf("\nuser_main: pthread_sigqueue test\n");
+ pthread_sigqueue_test();
+ check_test_memory_usage();
+#endif
+
/* Verify pthreads and condition variable timed waits */
printf("\nuser_main: timed wait test\n");
diff --git a/testing/ostest/pthread_sigqueue.c
b/testing/ostest/pthread_sigqueue.c
new file mode 100644
index 000000000..0b41904c5
--- /dev/null
+++ b/testing/ostest/pthread_sigqueue.c
@@ -0,0 +1,277 @@
+/****************************************************************************
+ * apps/testing/ostest/pthread_sigqueue.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 <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "ostest.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TEST_SIGNO SIGUSR1
+#define TEST_VAL_INT 42
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static sem_t g_ready_sem;
+static sem_t g_done_sem;
+static struct sigaction g_oact;
+static bool g_act_installed;
+static volatile bool g_sigreceived;
+static volatile int g_received_signo;
+static volatile int g_received_code;
+static volatile int g_received_val;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sigqueue_handler
+ ****************************************************************************/
+
+static void sigqueue_handler(int signo, FAR siginfo_t *info,
+ FAR void *ucontext)
+{
+ if (info != NULL)
+ {
+ g_received_signo = signo;
+ g_received_code = info->si_code;
+ g_received_val = info->si_value.sival_int;
+ g_sigreceived = true;
+ }
+
+ sem_post(&g_done_sem);
+}
+
+/****************************************************************************
+ * Name: sigqueue_thread
+ ****************************************************************************/
+
+static FAR void *sigqueue_thread(FAR void *arg)
+{
+ struct sigaction act;
+ sigset_t set;
+ int status;
+
+ /* Setup signal action */
+
+ act.sa_sigaction = sigqueue_handler;
+ act.sa_flags = SA_SIGINFO;
+ sigemptyset(&act.sa_mask);
+
+ status = sigaction(TEST_SIGNO, &act, &g_oact);
+ if (status != OK)
+ {
+ printf("sigqueue_thread: sigaction failed, errno=%d\n", errno);
+ ASSERT(false);
+ return (FAR void *)ERROR;
+ }
+
+ g_act_installed = true;
+
+ /* Unblock test signal */
+
+ sigemptyset(&set);
+ sigaddset(&set, TEST_SIGNO);
+ status = pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+ if (status != OK)
+ {
+ printf("sigqueue_thread: pthread_sigmask failed: %d\n", status);
+ ASSERT(false);
+ return (FAR void *)ERROR;
+ }
+
+ /* Notify sender that we are ready */
+
+ sem_post(&g_ready_sem);
+
+ /* Wait for signal delivery */
+
+ while (sem_wait(&g_done_sem) < 0)
+ {
+ if (errno != EINTR)
+ {
+ printf("sigqueue_thread: sem_wait failed: %d\n", errno);
+ ASSERT(false);
+ return (FAR void *)ERROR;
+ }
+ }
+
+ return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pthread_sigqueue_test
+ ****************************************************************************/
+
+void pthread_sigqueue_test(void)
+{
+ pthread_t thread;
+ union sigval val;
+ int status;
+
+ sem_init(&g_ready_sem, 0, 0);
+ sem_init(&g_done_sem, 0, 0);
+
+ g_sigreceived = false;
+ g_received_signo = -1;
+ g_received_code = -1;
+ g_received_val = -1;
+ g_act_installed = false;
+
+ /* Test 1: Invalid signal number error handling */
+
+ val.sival_int = TEST_VAL_INT;
+ status = pthread_sigqueue(pthread_self(), -1, val);
+ if (status != EINVAL)
+ {
+ printf("pthread_sigqueue_test: signo err: %d\n", status);
+ ASSERT(false);
+ }
+
+ /* Test 2: Invalid thread ID error handling */
+
+ status = pthread_sigqueue((pthread_t)-1, TEST_SIGNO, val);
+ if (status != ESRCH)
+ {
+ printf("pthread_sigqueue_test: thread err: %d\n", status);
+ ASSERT(false);
+ }
+
+ /* Test 3: Normal signal queuing to thread */
+
+ status = pthread_create(&thread, NULL, sigqueue_thread, NULL);
+ if (status != OK)
+ {
+ printf("pthread_sigqueue_test: pthread_create: %d\n", status);
+ ASSERT(false);
+ goto errout;
+ }
+
+ /* Wait until target thread has installed the handler and unblocked */
+
+ while (sem_wait(&g_ready_sem) < 0)
+ {
+ if (errno != EINTR)
+ {
+ printf("pthread_sigqueue_test: sem_wait: %d\n", errno);
+ ASSERT(false);
+ goto errout;
+ }
+ }
+
+ /* Send signal with payload to target thread */
+
+ status = pthread_sigqueue(thread, TEST_SIGNO, val);
+ if (status != OK)
+ {
+ printf("pthread_sigqueue_test: pthread_sigqueue: %d\n", status);
+ ASSERT(false);
+ goto errout;
+ }
+
+ /* Join target thread */
+
+ status = pthread_join(thread, NULL);
+ if (status != OK)
+ {
+ printf("pthread_sigqueue_test: pthread_join: %d\n", status);
+ ASSERT(false);
+ goto errout;
+ }
+
+ /* Restore signal action */
+
+ if (g_act_installed)
+ {
+ status = sigaction(TEST_SIGNO, &g_oact, NULL);
+ if (status != OK)
+ {
+ printf("pthread_sigqueue_test: sigaction restore: %d\n", errno);
+ ASSERT(false);
+ }
+
+ g_act_installed = false;
+ }
+
+ /* Verify received signal properties */
+
+ if (!g_sigreceived)
+ {
+ printf("pthread_sigqueue_test: signal not received\n");
+ ASSERT(false);
+ }
+
+ if (g_received_signo != TEST_SIGNO)
+ {
+ printf("pthread_sigqueue_test: signo mismatch: %d\n",
+ g_received_signo);
+ ASSERT(false);
+ }
+
+ if (g_received_code != SI_QUEUE)
+ {
+ printf("pthread_sigqueue_test: si_code mismatch: %d\n",
+ g_received_code);
+ ASSERT(false);
+ }
+
+ if (g_received_val != TEST_VAL_INT)
+ {
+ printf("pthread_sigqueue_test: val mismatch: %d\n",
+ g_received_val);
+ ASSERT(false);
+ }
+
+ printf("pthread_sigqueue_test: SUCCESS\n");
+
+errout:
+ if (g_act_installed)
+ {
+ sigaction(TEST_SIGNO, &g_oact, NULL);
+ g_act_installed = false;
+ }
+
+ sem_destroy(&g_ready_sem);
+ sem_destroy(&g_done_sem);
+}