summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Tests/Kernel/CMakeLists.txt1
-rw-r--r--Tests/Kernel/TestSigWait.cpp179
2 files changed, 180 insertions, 0 deletions
diff --git a/Tests/Kernel/CMakeLists.txt b/Tests/Kernel/CMakeLists.txt
index ef37bc29dc..4cec637dc3 100644
--- a/Tests/Kernel/CMakeLists.txt
+++ b/Tests/Kernel/CMakeLists.txt
@@ -42,6 +42,7 @@ set(LIBTEST_BASED_SOURCES
TestProcFS.cpp
TestProcFSWrite.cpp
TestSigAltStack.cpp
+ TestSigWait.cpp
)
foreach(libtest_source IN LISTS LIBTEST_BASED_SOURCES)
diff --git a/Tests/Kernel/TestSigWait.cpp b/Tests/Kernel/TestSigWait.cpp
new file mode 100644
index 0000000000..5e61199d10
--- /dev/null
+++ b/Tests/Kernel/TestSigWait.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibTest/TestCase.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+
+TEST_CASE(sigwait)
+{
+ sigset_t mask;
+
+ int rc = sigemptyset(&mask);
+ EXPECT_EQ(rc, 0);
+ rc = sigaddset(&mask, SIGUSR1);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+
+ int child_pid = fork();
+ EXPECT(child_pid >= 0);
+ if (child_pid == 0) {
+ sleep(1);
+ kill(getppid(), SIGUSR1);
+ exit(EXIT_SUCCESS);
+ } else {
+ int sig;
+ rc = sigwait(&mask, &sig);
+ EXPECT_EQ(rc, 0);
+ EXPECT_EQ(sig, SIGUSR1);
+ }
+
+ // cancel pending signal
+ struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_ignore, nullptr);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+ struct sigaction act_default = { { SIG_DFL }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_default, nullptr);
+ EXPECT_EQ(rc, 0);
+ sigset_t pending;
+ rc = sigpending(&pending);
+ EXPECT_EQ(rc, 0);
+ EXPECT_EQ(pending, 0u);
+}
+
+TEST_CASE(sigwaitinfo)
+{
+ sigset_t mask;
+
+ int rc = sigemptyset(&mask);
+ EXPECT_EQ(rc, 0);
+ rc = sigaddset(&mask, SIGUSR1);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+
+ int child_pid = fork();
+ EXPECT(child_pid >= 0);
+ if (child_pid == 0) {
+ sleep(1);
+ kill(getppid(), SIGUSR1);
+ exit(EXIT_SUCCESS);
+ } else {
+ siginfo_t info;
+ rc = sigwaitinfo(&mask, &info);
+ EXPECT_EQ(rc, SIGUSR1);
+ EXPECT_EQ(info.si_signo, SIGUSR1);
+ }
+
+ // cancel pending signal
+ struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_ignore, nullptr);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+ struct sigaction act_default = { { SIG_DFL }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_default, nullptr);
+ EXPECT_EQ(rc, 0);
+ sigset_t pending;
+ rc = sigpending(&pending);
+ EXPECT_EQ(rc, 0);
+ EXPECT_EQ(pending, 0u);
+}
+
+TEST_CASE(sigtimedwait_normal)
+{
+ sigset_t mask;
+
+ int rc = sigemptyset(&mask);
+ EXPECT_EQ(rc, 0);
+ rc = sigaddset(&mask, SIGUSR1);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+
+ int child_pid = fork();
+ EXPECT(child_pid >= 0);
+ if (child_pid == 0) {
+ sleep(1);
+ kill(getppid(), SIGUSR1);
+ exit(EXIT_SUCCESS);
+ } else {
+ siginfo_t info;
+ struct timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
+ rc = sigtimedwait(&mask, &info, &timeout);
+ EXPECT_EQ(rc, SIGUSR1);
+ EXPECT_EQ(info.si_signo, SIGUSR1);
+ }
+
+ // cancel pending signal
+ struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_ignore, nullptr);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+ struct sigaction act_default = { { SIG_DFL }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_default, nullptr);
+ EXPECT_EQ(rc, 0);
+ sigset_t pending;
+ rc = sigpending(&pending);
+ EXPECT_EQ(rc, 0);
+ EXPECT_EQ(pending, 0u);
+}
+
+TEST_CASE(sigtimedwait_poll)
+{
+ sigset_t mask;
+
+ int rc = sigemptyset(&mask);
+ EXPECT_EQ(rc, 0);
+ rc = sigaddset(&mask, SIGUSR1);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+
+ struct timespec poll_timeout = { .tv_sec = 0, .tv_nsec = 0 };
+ rc = sigtimedwait(&mask, nullptr, &poll_timeout);
+ EXPECT_EQ(rc, -1);
+ EXPECT_EQ(errno, EAGAIN);
+
+ kill(getpid(), SIGUSR1);
+
+ siginfo_t info;
+ rc = sigtimedwait(&mask, &info, &poll_timeout);
+ EXPECT_EQ(rc, SIGUSR1);
+ EXPECT_EQ(info.si_signo, SIGUSR1);
+
+ // cancel pending signal
+ struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_ignore, nullptr);
+ EXPECT_EQ(rc, 0);
+ rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
+ EXPECT_EQ(rc, 0);
+ struct sigaction act_default = { { SIG_DFL }, 0, 0 };
+ rc = sigaction(SIGUSR1, &act_default, nullptr);
+ EXPECT_EQ(rc, 0);
+ sigset_t pending;
+ rc = sigpending(&pending);
+ EXPECT_EQ(rc, 0);
+ EXPECT_EQ(pending, 0u);
+}
+
+TEST_CASE(sigtimedwait_timeout)
+{
+ sigset_t mask;
+ int rc = sigemptyset(&mask);
+ EXPECT_EQ(rc, 0);
+ rc = sigaddset(&mask, SIGUSR1);
+ EXPECT_EQ(rc, 0);
+ struct timespec timeout = { .tv_sec = 1, .tv_nsec = 0 };
+ rc = sigtimedwait(&mask, nullptr, &timeout);
+ EXPECT_EQ(rc, -1);
+ EXPECT_EQ(errno, EAGAIN);
+}