1276479Sdim/*
2249259Sdim * Copyright (c) 2009 Mark Heily <mark@heily.com>
3249259Sdim *
4249259Sdim * Permission to use, copy, modify, and distribute this software for any
5249259Sdim * purpose with or without fee is hereby granted, provided that the above
6249259Sdim * copyright notice and this permission notice appear in all copies.
7249259Sdim *
8249259Sdim * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9249259Sdim * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10276479Sdim * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11249259Sdim * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12249259Sdim * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13249259Sdim * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14276479Sdim * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15280031Sdim *
16249259Sdim * $FreeBSD: stable/10/tests/sys/kqueue/libkqueue/signal.c 305467 2016-09-06 08:45:29Z ngie $
17276479Sdim */
18276479Sdim
19249259Sdim#include "common.h"
20276479Sdim
21249259Sdimint kqfd;
22276479Sdim
23276479Sdimvoid
24276479Sdimtest_kevent_signal_add(void)
25276479Sdim{
26276479Sdim    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)";
27249259Sdim    struct kevent kev;
28249259Sdim
29249259Sdim    test_begin(test_id);
30276479Sdim
31276479Sdim    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
32276479Sdim    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
33249259Sdim        err(1, "%s", test_id);
34296417Sdim
35296417Sdim    success();
36296417Sdim}
37296417Sdim
38296417Sdimvoid
39276479Sdimtest_kevent_signal_get(void)
40276479Sdim{
41276479Sdim    const char *test_id = "kevent(EVFILT_SIGNAL, wait)";
42261991Sdim    struct kevent kev;
43276479Sdim
44276479Sdim    test_begin(test_id);
45249259Sdim
46276479Sdim    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
47276479Sdim    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
48249259Sdim        err(1, "%s", test_id);
49249259Sdim
50288943Sdim    /* Block SIGUSR1, then send it to ourselves */
51280031Sdim    sigset_t mask;
52280031Sdim    sigemptyset(&mask);
53276479Sdim    sigaddset(&mask, SIGUSR1);
54296417Sdim    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
55296417Sdim        err(1, "sigprocmask");
56296417Sdim    if (kill(getpid(), SIGUSR1) < 0)
57296417Sdim        err(1, "kill");
58296417Sdim
59288943Sdim    kev.flags |= EV_CLEAR;
60288943Sdim    kev.data = 1;
61261991Sdim    kevent_cmp(&kev, kevent_get(kqfd));
62276479Sdim
63276479Sdim    success();
64276479Sdim}
65276479Sdim
66276479Sdimvoid
67288943Sdimtest_kevent_signal_disable(void)
68276479Sdim{
69276479Sdim    const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)";
70276479Sdim    struct kevent kev;
71276479Sdim
72276479Sdim    test_begin(test_id);
73276479Sdim
74276479Sdim    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL);
75280031Sdim    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
76288943Sdim        err(1, "%s", test_id);
77280031Sdim
78280031Sdim    /* Block SIGUSR1, then send it to ourselves */
79280031Sdim    sigset_t mask;
80280031Sdim    sigemptyset(&mask);
81280031Sdim    sigaddset(&mask, SIGUSR1);
82280031Sdim    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
83276479Sdim        err(1, "sigprocmask");
84276479Sdim    if (kill(getpid(), SIGUSR1) < 0)
85276479Sdim        err(1, "kill");
86276479Sdim
87276479Sdim    test_no_kevents();
88276479Sdim
89276479Sdim    success();
90276479Sdim}
91276479Sdim
92276479Sdimvoid
93276479Sdimtest_kevent_signal_enable(void)
94288943Sdim{
95261991Sdim    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)";
96276479Sdim    struct kevent kev;
97276479Sdim
98261991Sdim    test_begin(test_id);
99261991Sdim
100276479Sdim    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL);
101261991Sdim    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
102261991Sdim        err(1, "%s", test_id);
103276479Sdim
104276479Sdim    /* Block SIGUSR1, then send it to ourselves */
105276479Sdim    sigset_t mask;
106276479Sdim    sigemptyset(&mask);
107276479Sdim    sigaddset(&mask, SIGUSR1);
108276479Sdim    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
109276479Sdim        err(1, "sigprocmask");
110276479Sdim    if (kill(getpid(), SIGUSR1) < 0)
111276479Sdim        err(1, "kill");
112249259Sdim
113276479Sdim    kev.flags = EV_ADD | EV_CLEAR;
114249259Sdim#if LIBKQUEUE
115276479Sdim    kev.data = 1; /* WORKAROUND */
116276479Sdim#else
117276479Sdim    kev.data = 2; // one extra time from test_kevent_signal_disable()
118276479Sdim#endif
119276479Sdim    kevent_cmp(&kev, kevent_get(kqfd));
120276479Sdim
121276479Sdim    /* Delete the watch */
122276479Sdim    kev.flags = EV_DELETE;
123296417Sdim    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
124296417Sdim        err(1, "%s", test_id);
125296417Sdim
126296417Sdim    success();
127296417Sdim}
128276479Sdim
129276479Sdimvoid
130276479Sdimtest_kevent_signal_del(void)
131276479Sdim{
132276479Sdim    const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)";
133280031Sdim    struct kevent kev;
134296417Sdim
135296417Sdim    test_begin(test_id);
136296417Sdim
137296417Sdim    /* Delete the kevent */
138296417Sdim    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL);
139296417Sdim    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
140296417Sdim        err(1, "%s", test_id);
141296417Sdim
142296417Sdim    /* Block SIGUSR1, then send it to ourselves */
143296417Sdim    sigset_t mask;
144296417Sdim    sigemptyset(&mask);
145296417Sdim    sigaddset(&mask, SIGUSR1);
146296417Sdim    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
147280031Sdim        err(1, "sigprocmask");
148280031Sdim    if (kill(getpid(), SIGUSR1) < 0)
149280031Sdim        err(1, "kill");
150280031Sdim
151280031Sdim    test_no_kevents();
152280031Sdim    success();
153280031Sdim}
154
155void
156test_kevent_signal_oneshot(void)
157{
158    const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)";
159    struct kevent kev;
160
161    test_begin(test_id);
162
163    EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL);
164    if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0)
165        err(1, "%s", test_id);
166
167    /* Block SIGUSR1, then send it to ourselves */
168    sigset_t mask;
169    sigemptyset(&mask);
170    sigaddset(&mask, SIGUSR1);
171    if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
172        err(1, "sigprocmask");
173    if (kill(getpid(), SIGUSR1) < 0)
174        err(1, "kill");
175
176    kev.flags |= EV_CLEAR;
177    kev.data = 1;
178    kevent_cmp(&kev, kevent_get(kqfd));
179
180    /* Send another one and make sure we get no events */
181    if (kill(getpid(), SIGUSR1) < 0)
182        err(1, "kill");
183    test_no_kevents();
184
185    success();
186}
187
188void
189test_evfilt_signal()
190{
191	kqfd = kqueue();
192        test_kevent_signal_add();
193        test_kevent_signal_del();
194        test_kevent_signal_get();
195        test_kevent_signal_disable();
196        test_kevent_signal_enable();
197        test_kevent_signal_oneshot();
198	close(kqfd);
199}
200