aboutsummaryrefslogtreecommitdiff
path: root/testcases/kernel
diff options
context:
space:
mode:
authorMatthias Maennich <maennich@google.com>2019-03-19 18:41:36 +0000
committerPetr Vorel <pvorel@suse.cz>2019-03-21 19:15:27 +0100
commit6c3e9b6da3717c420bda2ef69e41f53ad58001fa (patch)
treed7f800c23f8858b5e677d7f05645b5a88d6dcb61 /testcases/kernel
parentb03885fffbd51bc61b7f4e0014774ed0f5dd6569 (diff)
sigpending/rt_sigpending: add basic test
Test basic functionality of sigpending/rt_sigpending. Signed-off-by: Matthias Maennich <maennich@google.com> Signed-off-by: Petr Vorel <pvorel@suse.cz>
Diffstat (limited to 'testcases/kernel')
-rw-r--r--testcases/kernel/syscalls/sigpending/sigpending02.c113
1 files changed, 102 insertions, 11 deletions
diff --git a/testcases/kernel/syscalls/sigpending/sigpending02.c b/testcases/kernel/syscalls/sigpending/sigpending02.c
index 70dda858d..0419fbedb 100644
--- a/testcases/kernel/syscalls/sigpending/sigpending02.c
+++ b/testcases/kernel/syscalls/sigpending/sigpending02.c
@@ -4,14 +4,18 @@
*
* AUTHORS
* Paul Larson
+ * Matthias Maennich
*
* DESCRIPTION
- * Test to see that the proper errors are returned by sigpending. All the
- * tests can also be compiled to use the rt_sigpending syscall instead. To
- * simplify the documentation, only sigpending() is usually mentioned
- * below.
+ * Test to assert basic functionality of sigpending. All the tests can also be
+ * compiled to use the rt_sigpending syscall instead. To simplify the
+ * documentation, only sigpending() is usually mentioned below.
*
* Test 1:
+ * Suppress handling SIGUSR1 and SIGUSR1, raise them and assert their
+ * signal pending.
+ *
+ * Test 2:
* Call sigpending(sigset_t*=-1), it should return -1 with errno EFAULT
*/
@@ -23,19 +27,100 @@
#include "ltp_signal.h"
#include "lapi/syscalls.h"
-static void run(void)
-{
- /* set sigset to point to an invalid location */
- sigset_t *sigset = (sigset_t *) - 1;
-
#if defined(TEST_SIGPENDING)
- TEST(tst_syscall(__NR_sigpending, sigset));
+#define tested_sigpending(sigset) TEST(tst_syscall(__NR_sigpending, sigset))
#elif defined(TEST_RT_SIGPENDING)
- TEST(tst_syscall(__NR_rt_sigpending, sigset, SIGSETSIZE));
+#define tested_sigpending(sigset) \
+ TEST(tst_syscall(__NR_rt_sigpending, sigset, SIGSETSIZE))
#else
#error Neither TEST_SIGPENDING nor TEST_RT_SIGPENDING is defined!
#endif
+static int sighandler_counter;
+static void sighandler(int signum LTP_ATTRIBUTE_UNUSED)
+{
+ ++sighandler_counter;
+}
+
+static void test_sigpending(void)
+{
+ int SIGMAX = MIN(sizeof(sigset_t) * 8, (size_t)_NSIG);
+
+ int i; /* loop index */
+
+ /* set up signal mask and handler */
+ sigset_t only_SIGUSR, old_mask;
+ sighandler_t old_sighandler1, old_sighandler2;
+ sigemptyset(&only_SIGUSR);
+ sigaddset(&only_SIGUSR, SIGUSR1);
+ sigaddset(&only_SIGUSR, SIGUSR2);
+ if (sigprocmask(SIG_SETMASK, &only_SIGUSR, &old_mask))
+ tst_brk(TBROK, "sigprocmask failed");
+ old_sighandler1 = SAFE_SIGNAL(SIGUSR1, sighandler);
+ old_sighandler2 = SAFE_SIGNAL(SIGUSR2, sighandler);
+
+ /* Initially no signal should be pending */
+ sigset_t pending;
+ sigemptyset(&pending);
+ tested_sigpending(&pending);
+
+ for (i = 1; i < SIGMAX; ++i)
+ if (sigismember(&pending, i))
+ tst_brk(TFAIL,
+ "initialization failed: no signal should be pending by now");
+
+ /* raise a signal */
+ if (raise(SIGUSR1))
+ tst_brk(TBROK, "raising SIGUSR1 failed");
+ if (sighandler_counter > 0)
+ tst_brk(TFAIL,
+ "signal handler is not (yet) supposed to be called");
+
+ /* now we should have exactly one pending signal (SIGUSR1) */
+ sigemptyset(&pending);
+ tested_sigpending(&pending);
+ for (i = 1; i < SIGMAX; ++i)
+ if ((i == SIGUSR1) != sigismember(&pending, i))
+ tst_brk(TFAIL, "only SIGUSR1 should be pending by now");
+
+ /* raise another signal */
+ if (raise(SIGUSR2))
+ tst_brk(TBROK, "raising SIGUSR2 failed");
+ if (sighandler_counter > 0)
+ tst_brk(TFAIL,
+ "signal handler is not (yet) supposed to be called");
+
+ /* now we should have exactly two pending signals (SIGUSR1, SIGUSR2) */
+ sigemptyset(&pending);
+ tested_sigpending(&pending);
+ for (i = 1; i < SIGMAX; ++i)
+ if ((i == SIGUSR1 || i == SIGUSR2) != sigismember(&pending, i))
+ tst_brk(TFAIL,
+ "only SIGUSR1, SIGUSR2 should be pending by now");
+
+ tst_res(TPASS, "basic sigpending test successful");
+
+ /* reinstate old mask */
+ if (sigprocmask(SIG_SETMASK, &old_mask, NULL))
+ tst_brk(TBROK, "sigprocmask failed");
+
+ /* at this time the signal handler has been called, once for each signal */
+ if (sighandler_counter != 2)
+ tst_brk(TFAIL,
+ "signal handler has not been called for each signal");
+
+ /* reinstate the original signal handlers */
+ SAFE_SIGNAL(SIGUSR1, old_sighandler1);
+ SAFE_SIGNAL(SIGUSR2, old_sighandler2);
+}
+
+static void test_efault_on_invalid_sigset(void)
+{
+ /* set sigset to point to an invalid location */
+ sigset_t *sigset = (sigset_t *)-1;
+
+ tested_sigpending(sigset);
+
/* check return code */
if (TST_RET == -1) {
if (TST_ERR != EFAULT) {
@@ -52,6 +137,12 @@ static void run(void)
}
}
+static void run(void)
+{
+ test_sigpending();
+ test_efault_on_invalid_sigset();
+}
+
static struct tst_test test = {
.test_all = run
};