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 * $FreeBSD$ 17 */ 18 19#include <sys/stat.h> 20 21#include <err.h> 22 23#include "config.h" 24#include "common.h" 25 26static int sigusr1_caught = 0; 27 28int kqfd; 29 30static void 31sig_handler(int signum) 32{ 33 sigusr1_caught = 1; 34} 35 36static void 37add_and_delete(void) 38{ 39 struct kevent kev; 40 pid_t pid; 41 42 /* Create a child that waits to be killed and then exits */ 43 pid = fork(); 44 if (pid == 0) { 45 struct stat s; 46 if (fstat(kqfd, &s) != -1) 47 errx(1, "kqueue inherited across fork! (%s() at %s:%d)", 48 __func__, __FILE__, __LINE__); 49 50 pause(); 51 exit(2); 52 } 53 printf(" -- child created (pid %d)\n", (int) pid); 54 55 test_begin("kevent(EVFILT_PROC, EV_ADD)"); 56 57 test_no_kevents(); 58 kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); 59 test_no_kevents(); 60 61 success(); 62 63 test_begin("kevent(EVFILT_PROC, EV_DELETE)"); 64 65 sleep(1); 66 test_no_kevents(); 67 kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_DELETE, 0, 0, NULL); 68 if (kill(pid, SIGKILL) < 0) 69 err(1, "kill"); 70 sleep(1); 71 test_no_kevents(); 72 73 success(); 74 75} 76 77#ifdef TODO 78static void 79event_trigger(void) 80{ 81 struct kevent kev; 82 pid_t pid; 83 84 test_begin("kevent(EVFILT_PROC, wait)"); 85 86 /* Create a child that waits to be killed and then exits */ 87 pid = fork(); 88 if (pid == 0) { 89 pause(); 90 printf(" -- child caught signal, exiting\n"); 91 exit(2); 92 } 93 printf(" -- child created (pid %d)\n", (int) pid); 94 95 test_no_kevents(); 96 kevent_add(kqfd, &kev, pid, EVFILT_PROC, EV_ADD, 0, 0, NULL); 97 98 /* Cause the child to exit, then retrieve the event */ 99 printf(" -- killing process %d\n", (int) pid); 100 if (kill(pid, SIGUSR1) < 0) 101 err(1, "kill"); 102 kevent_cmp(&kev, kevent_get(kqfd)); 103 test_no_kevents(); 104 105 success(); 106} 107 108void 109test_kevent_signal_disable(void) 110{ 111 const char *test_id = "kevent(EVFILT_SIGNAL, EV_DISABLE)"; 112 struct kevent kev; 113 114 test_begin(test_id); 115 116 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DISABLE, 0, 0, NULL); 117 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 118 err(1, "%s", test_id); 119 120 /* Block SIGUSR1, then send it to ourselves */ 121 sigset_t mask; 122 sigemptyset(&mask); 123 sigaddset(&mask, SIGUSR1); 124 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 125 err(1, "sigprocmask"); 126 if (kill(getpid(), SIGKILL) < 0) 127 err(1, "kill"); 128 129 test_no_kevents(); 130 131 success(); 132} 133 134void 135test_kevent_signal_enable(void) 136{ 137 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ENABLE)"; 138 struct kevent kev; 139 140 test_begin(test_id); 141 142 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ENABLE, 0, 0, NULL); 143 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 144 err(1, "%s", test_id); 145 146 /* Block SIGUSR1, then send it to ourselves */ 147 sigset_t mask; 148 sigemptyset(&mask); 149 sigaddset(&mask, SIGUSR1); 150 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 151 err(1, "sigprocmask"); 152 if (kill(getpid(), SIGUSR1) < 0) 153 err(1, "kill"); 154 155 kev.flags = EV_ADD | EV_CLEAR; 156#if LIBKQUEUE 157 kev.data = 1; /* WORKAROUND */ 158#else 159 kev.data = 2; // one extra time from test_kevent_signal_disable() 160#endif 161 kevent_cmp(&kev, kevent_get(kqfd)); 162 163 /* Delete the watch */ 164 kev.flags = EV_DELETE; 165 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 166 err(1, "%s", test_id); 167 168 success(); 169} 170 171void 172test_kevent_signal_del(void) 173{ 174 const char *test_id = "kevent(EVFILT_SIGNAL, EV_DELETE)"; 175 struct kevent kev; 176 177 test_begin(test_id); 178 179 /* Delete the kevent */ 180 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_DELETE, 0, 0, NULL); 181 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 182 err(1, "%s", test_id); 183 184 /* Block SIGUSR1, then send it to ourselves */ 185 sigset_t mask; 186 sigemptyset(&mask); 187 sigaddset(&mask, SIGUSR1); 188 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 189 err(1, "sigprocmask"); 190 if (kill(getpid(), SIGUSR1) < 0) 191 err(1, "kill"); 192 193 test_no_kevents(); 194 success(); 195} 196 197void 198test_kevent_signal_oneshot(void) 199{ 200 const char *test_id = "kevent(EVFILT_SIGNAL, EV_ONESHOT)"; 201 struct kevent kev; 202 203 test_begin(test_id); 204 205 EV_SET(&kev, SIGUSR1, EVFILT_SIGNAL, EV_ADD | EV_ONESHOT, 0, 0, NULL); 206 if (kevent(kqfd, &kev, 1, NULL, 0, NULL) < 0) 207 err(1, "%s", test_id); 208 209 /* Block SIGUSR1, then send it to ourselves */ 210 sigset_t mask; 211 sigemptyset(&mask); 212 sigaddset(&mask, SIGUSR1); 213 if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) 214 err(1, "sigprocmask"); 215 if (kill(getpid(), SIGUSR1) < 0) 216 err(1, "kill"); 217 218 kev.flags |= EV_CLEAR; 219 kev.data = 1; 220 kevent_cmp(&kev, kevent_get(kqfd)); 221 222 /* Send another one and make sure we get no events */ 223 if (kill(getpid(), SIGUSR1) < 0) 224 err(1, "kill"); 225 test_no_kevents(); 226 227 success(); 228} 229#endif 230 231void 232test_evfilt_proc() 233{ 234 kqfd = kqueue(); 235 236 signal(SIGUSR1, sig_handler); 237 238 add_and_delete(); 239 240#if TODO 241 event_trigger(); 242#endif 243 244 signal(SIGUSR1, SIG_DFL); 245 246#if TODO 247 test_kevent_signal_add(); 248 test_kevent_signal_del(); 249 test_kevent_signal_get(); 250 test_kevent_signal_disable(); 251 test_kevent_signal_enable(); 252 test_kevent_signal_oneshot(); 253#endif 254 close(kqfd); 255} 256