1 /* $OpenBSD: kqueue-signal.c,v 1.3 2016/09/20 23:05:27 bluhm Exp $ */
2 /*
3 * Written by Philip Guenther <guenther@openbsd.org> 2011 Public Domain
4 */
5
6 #include <sys/types.h>
7 #include <sys/event.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <sys/wait.h>
11
12 #include <err.h>
13 #include <errno.h>
14 #include <signal.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 #include "main.h"
21
22 volatile sig_atomic_t saw_usr1 = 0;
23 volatile sig_atomic_t result = 0;
24 int kq;
25
26 int
sigtest(int signum,int catch)27 sigtest(int signum, int catch)
28 {
29 struct kevent ke;
30 struct timespec ts;
31
32 ts.tv_sec = 10;
33 ts.tv_nsec = 0;
34
35 ASS(kevent(kq, NULL, 0, &ke, 1, &ts) == 1,
36 warn("can't fetch event on kqueue"));
37 ASSX(ke.filter == EVFILT_SIGNAL);
38 ASSX(ke.ident == signum);
39 ASSX(ke.data == catch);
40 return (0);
41 }
42
43 void
usr1handler(int signum)44 usr1handler(int signum)
45 {
46 saw_usr1 = 1;
47 result = sigtest(SIGUSR1, 1);
48 }
49
50 int
do_signal(void)51 do_signal(void)
52 {
53 struct kevent ke;
54 pid_t pid = getpid();
55 sigset_t mask;
56
57 ASS((kq = kqueue()) >= 0, warn("kqueue"));
58
59 signal(SIGUSR1, usr1handler);
60 signal(SIGUSR2, SIG_IGN);
61
62 EV_SET(&ke, SIGUSR1, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, NULL);
63 ASS(kevent(kq, &ke, 1, NULL, 0, NULL) == 0,
64 warn("can't register events on kqueue"));
65 EV_SET(&ke, SIGUSR2, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, NULL);
66 ASS(kevent(kq, &ke, 1, NULL, 0, NULL) == 0,
67 warn("can't register events on kqueue"));
68
69 EV_SET(&ke, 10000, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, NULL);
70 ASS(kevent(kq, &ke, 1, NULL, 0, NULL) != 0,
71 warnx("registered bogus signal on kqueue"));
72 ASS(errno == EINVAL,
73 warn("registering bogus signal on kqueue returned wrong error"));
74
75 ASSX(saw_usr1 == 0);
76 kill(pid, SIGUSR1);
77 ASSX(saw_usr1 == 1);
78
79 kill(pid, SIGUSR2);
80 ASSX(sigtest(SIGUSR2, 1) == 0);
81 kill(pid, SIGUSR2);
82 kill(pid, SIGUSR2);
83 ASSX(sigtest(SIGUSR2, 2) == 0);
84
85 sigemptyset(&mask);
86 sigaddset(&mask, SIGUSR1);
87 sigaddset(&mask, SIGUSR2);
88 sigprocmask(SIG_BLOCK, &mask, NULL);
89
90 signal(SIGUSR1, SIG_DFL);
91 kill(pid, SIGUSR1);
92 kill(pid, SIGUSR2);
93
94 close(kq);
95
96 return (0);
97 }
98