1 /* 2 * Copyright (c) 2009 Mark Heily <mark@heily.com> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "common.h" 18 19 20 static void 21 test_kevent_signal_add(void) 22 { 23 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ADD)"; 24 struct kevent kev; 25 26 test_begin(test_id); 27 28 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); 29 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 30 err(1, "%s", test_id); 31 32 success(); 33 } 34 35 static void 36 test_kevent_signal_get(void) 37 { 38 const char *test_id = "kevent(EVFILT_SIGNAL, wait)"; 39 struct kevent kev; 40 41 test_begin(test_id); 42 43 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); 44 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 45 err(1, "%s", test_id); 46 47 /* Block SIGUSR1, then send it to ourselves */ 48 sigset_t mask; 49 sigemptyset(&mask); 50 sigaddset(&mask, SIGUSR1); 51 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 52 err(1, "sigprocmask"); 53 if (kill(getpid(), SIGUSR1) < 0) 54 err(1, "kill"); 55 56 kev.flags |= EV_CLEAR; 57 kev.data = 1; 58 kevent_cmp(&kev, kevent_get(kqfd)); 59 60 success(); 61 } 62 63 static void 64 test_kevent_signal_disable(void) 65 { 66 const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; 67 struct kevent kev; 68 69 test_begin(test_id); 70 71 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); 72 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 73 err(1, "%s", test_id); 74 75 /* Block SIGUSR1, then send it to ourselves */ 76 sigset_t mask; 77 sigemptyset(&mask); 78 sigaddset(&mask, SIGUSR1); 79 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 80 err(1, "sigprocmask"); 81 if (kill(getpid(), SIGUSR1) < 0) 82 err(1, "kill"); 83 84 test_no_kevents(); 85 86 success(); 87 } 88 89 static void 90 test_kevent_signal_enable(void) 91 { 92 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; 93 struct kevent kev; 94 95 test_begin(test_id); 96 97 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); 98 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 99 err(1, "%s", test_id); 100 101 /* Block SIGUSR1, then send it to ourselves */ 102 sigset_t mask; 103 sigemptyset(&mask); 104 sigaddset(&mask, SIGUSR1); 105 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 106 err(1, "sigprocmask"); 107 if (kill(getpid(), SIGUSR1) < 0) 108 err(1, "kill"); 109 110 kev.flags = EV_ADD | EV_CLEAR; 111 #if LIBKQUEUE 112 kev.data = 1; /* WORKAROUND */ 113 #else 114 kev.data = 2; // one extra time from test_kevent_signal_disable() 115 #endif 116 kevent_cmp(&kev, kevent_get(kqfd)); 117 118 /* Delete the watch */ 119 kev.flags = EV_DELETE; 120 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 121 err(1, "%s", test_id); 122 123 success(); 124 } 125 126 static void 127 test_kevent_signal_del(void) 128 { 129 const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; 130 struct kevent kev; 131 132 test_begin(test_id); 133 134 /* Delete the kevent */ 135 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); 136 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 137 err(1, "%s", test_id); 138 139 /* Block SIGUSR1, then send it to ourselves */ 140 sigset_t mask; 141 sigemptyset(&mask); 142 sigaddset(&mask, SIGUSR1); 143 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 144 err(1, "sigprocmask"); 145 if (kill(getpid(), SIGUSR1) < 0) 146 err(1, "kill"); 147 148 test_no_kevents(); 149 success(); 150 } 151 152 static void 153 test_kevent_signal_oneshot(void) 154 { 155 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; 156 struct kevent kev; 157 158 test_begin(test_id); 159 160 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); 161 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 162 err(1, "%s", test_id); 163 164 /* Block SIGUSR1, then send it to ourselves */ 165 sigset_t mask; 166 sigemptyset(&mask); 167 sigaddset(&mask, SIGUSR1); 168 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 169 err(1, "sigprocmask"); 170 if (kill(getpid(), SIGUSR1) < 0) 171 err(1, "kill"); 172 173 kev.flags |= EV_CLEAR; 174 kev.data = 1; 175 kevent_cmp(&kev, kevent_get(kqfd)); 176 177 /* Send another one and make sure we get no events */ 178 if (kill(getpid(), SIGUSR1) < 0) 179 err(1, "kill"); 180 test_no_kevents(); 181 182 success(); 183 } 184 185 void 186 test_evfilt_signal(void) 187 { 188 kqfd = kqueue(); 189 test_kevent_signal_add(); 190 test_kevent_signal_del(); 191 test_kevent_signal_get(); 192 test_kevent_signal_disable(); 193 test_kevent_signal_enable(); 194 test_kevent_signal_oneshot(); 195 close(kqfd); 196 } 197