Serenity Operating System
1/*
2 * Copyright (c) 2021, Idan Horowitz <idan.horowitz@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibTest/TestCase.h>
8#include <signal.h>
9#include <time.h>
10#include <unistd.h>
11
12TEST_CASE(sigwait)
13{
14 sigset_t mask;
15
16 int rc = sigemptyset(&mask);
17 EXPECT_EQ(rc, 0);
18 rc = sigaddset(&mask, SIGUSR1);
19 EXPECT_EQ(rc, 0);
20 rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
21 EXPECT_EQ(rc, 0);
22
23 int child_pid = fork();
24 EXPECT(child_pid >= 0);
25 if (child_pid == 0) {
26 sleep(1);
27 kill(getppid(), SIGUSR1);
28 exit(EXIT_SUCCESS);
29 } else {
30 int sig;
31 rc = sigwait(&mask, &sig);
32 EXPECT_EQ(rc, 0);
33 EXPECT_EQ(sig, SIGUSR1);
34 }
35
36 // cancel pending signal
37 struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
38 rc = sigaction(SIGUSR1, &act_ignore, nullptr);
39 EXPECT_EQ(rc, 0);
40 rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
41 EXPECT_EQ(rc, 0);
42 struct sigaction act_default = { { SIG_DFL }, 0, 0 };
43 rc = sigaction(SIGUSR1, &act_default, nullptr);
44 EXPECT_EQ(rc, 0);
45 sigset_t pending;
46 rc = sigpending(&pending);
47 EXPECT_EQ(rc, 0);
48 EXPECT_EQ(pending, 0u);
49}
50
51TEST_CASE(sigwaitinfo)
52{
53 sigset_t mask;
54
55 int rc = sigemptyset(&mask);
56 EXPECT_EQ(rc, 0);
57 rc = sigaddset(&mask, SIGUSR1);
58 EXPECT_EQ(rc, 0);
59 rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
60 EXPECT_EQ(rc, 0);
61
62 int child_pid = fork();
63 EXPECT(child_pid >= 0);
64 if (child_pid == 0) {
65 sleep(1);
66 kill(getppid(), SIGUSR1);
67 exit(EXIT_SUCCESS);
68 } else {
69 siginfo_t info;
70 rc = sigwaitinfo(&mask, &info);
71 EXPECT_EQ(rc, SIGUSR1);
72 EXPECT_EQ(info.si_signo, SIGUSR1);
73 }
74
75 // cancel pending signal
76 struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
77 rc = sigaction(SIGUSR1, &act_ignore, nullptr);
78 EXPECT_EQ(rc, 0);
79 rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
80 EXPECT_EQ(rc, 0);
81 struct sigaction act_default = { { SIG_DFL }, 0, 0 };
82 rc = sigaction(SIGUSR1, &act_default, nullptr);
83 EXPECT_EQ(rc, 0);
84 sigset_t pending;
85 rc = sigpending(&pending);
86 EXPECT_EQ(rc, 0);
87 EXPECT_EQ(pending, 0u);
88}
89
90TEST_CASE(sigtimedwait_normal)
91{
92 sigset_t mask;
93
94 int rc = sigemptyset(&mask);
95 EXPECT_EQ(rc, 0);
96 rc = sigaddset(&mask, SIGUSR1);
97 EXPECT_EQ(rc, 0);
98 rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
99 EXPECT_EQ(rc, 0);
100
101 int child_pid = fork();
102 EXPECT(child_pid >= 0);
103 if (child_pid == 0) {
104 sleep(1);
105 kill(getppid(), SIGUSR1);
106 exit(EXIT_SUCCESS);
107 } else {
108 siginfo_t info;
109 struct timespec timeout = { .tv_sec = 2, .tv_nsec = 0 };
110 rc = sigtimedwait(&mask, &info, &timeout);
111 EXPECT_EQ(rc, SIGUSR1);
112 EXPECT_EQ(info.si_signo, SIGUSR1);
113 }
114
115 // cancel pending signal
116 struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
117 rc = sigaction(SIGUSR1, &act_ignore, nullptr);
118 EXPECT_EQ(rc, 0);
119 rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
120 EXPECT_EQ(rc, 0);
121 struct sigaction act_default = { { SIG_DFL }, 0, 0 };
122 rc = sigaction(SIGUSR1, &act_default, nullptr);
123 EXPECT_EQ(rc, 0);
124 sigset_t pending;
125 rc = sigpending(&pending);
126 EXPECT_EQ(rc, 0);
127 EXPECT_EQ(pending, 0u);
128}
129
130TEST_CASE(sigtimedwait_poll)
131{
132 sigset_t mask;
133
134 int rc = sigemptyset(&mask);
135 EXPECT_EQ(rc, 0);
136 rc = sigaddset(&mask, SIGUSR1);
137 EXPECT_EQ(rc, 0);
138 rc = sigprocmask(SIG_BLOCK, &mask, nullptr);
139 EXPECT_EQ(rc, 0);
140
141 struct timespec poll_timeout = { .tv_sec = 0, .tv_nsec = 0 };
142 rc = sigtimedwait(&mask, nullptr, &poll_timeout);
143 EXPECT_EQ(rc, -1);
144 EXPECT_EQ(errno, EAGAIN);
145
146 kill(getpid(), SIGUSR1);
147
148 siginfo_t info;
149 rc = sigtimedwait(&mask, &info, &poll_timeout);
150 EXPECT_EQ(rc, SIGUSR1);
151 EXPECT_EQ(info.si_signo, SIGUSR1);
152
153 // cancel pending signal
154 struct sigaction act_ignore = { { SIG_IGN }, 0, 0 };
155 rc = sigaction(SIGUSR1, &act_ignore, nullptr);
156 EXPECT_EQ(rc, 0);
157 rc = sigprocmask(SIG_UNBLOCK, &mask, nullptr);
158 EXPECT_EQ(rc, 0);
159 struct sigaction act_default = { { SIG_DFL }, 0, 0 };
160 rc = sigaction(SIGUSR1, &act_default, nullptr);
161 EXPECT_EQ(rc, 0);
162 sigset_t pending;
163 rc = sigpending(&pending);
164 EXPECT_EQ(rc, 0);
165 EXPECT_EQ(pending, 0u);
166}
167
168TEST_CASE(sigtimedwait_timeout)
169{
170 sigset_t mask;
171 int rc = sigemptyset(&mask);
172 EXPECT_EQ(rc, 0);
173 rc = sigaddset(&mask, SIGUSR1);
174 EXPECT_EQ(rc, 0);
175 struct timespec timeout = { .tv_sec = 1, .tv_nsec = 0 };
176 rc = sigtimedwait(&mask, nullptr, &timeout);
177 EXPECT_EQ(rc, -1);
178 EXPECT_EQ(errno, EAGAIN);
179}