1 /* $OpenBSD: kqueue-signal.c,v 1.1 2011/07/07 02:00:51 guenther 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 <stdlib.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include <err.h> 16 #include <errno.h> 17 #include <unistd.h> 18 #include <signal.h> 19 20 #define ASS(cond, mess) do { if (!(cond)) { mess; return 1; } } while (0) 21 22 #define ASSX(cond) ASS(cond, warnx("assertion " #cond " failed on line %d", __LINE__)) 23 24 volatile sig_atomic_t saw_usr1 = 0; 25 volatile sig_atomic_t result = 0; 26 int kq; 27 28 int 29 sigtest(int signum, int catch) 30 { 31 struct kevent ke; 32 struct timespec ts; 33 34 ts.tv_sec = 10; 35 ts.tv_nsec = 0; 36 37 ASS(kevent(kq, NULL, 0, &ke, 1, &ts) == 1, 38 warn("can't fetch event on kqueue")); 39 ASSX(ke.filter == EVFILT_SIGNAL); 40 ASSX(ke.ident == signum); 41 ASSX(ke.data == catch); 42 return (0); 43 } 44 45 void 46 usr1handler(int signum) 47 { 48 saw_usr1 = 1; 49 result = sigtest(SIGUSR1, 1); 50 } 51 52 53 int do_signal(void); 54 55 int 56 do_signal(void) 57 { 58 struct kevent ke; 59 pid_t pid = getpid(); 60 sigset_t mask; 61 62 ASS((kq = kqueue()) >= 0, warn("kqueue")); 63 64 signal(SIGUSR1, usr1handler); 65 signal(SIGUSR2, SIG_IGN); 66 67 EV_SET(&ke, SIGUSR1, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, NULL); 68 ASS(kevent(kq, &ke, 1, NULL, 0, NULL) == 0, 69 warn("can't register events on kqueue")); 70 EV_SET(&ke, SIGUSR2, EVFILT_SIGNAL, EV_ADD|EV_ENABLE, 0, 0, NULL); 71 ASS(kevent(kq, &ke, 1, NULL, 0, NULL) == 0, 72 warn("can't register events on kqueue")); 73 74 ASSX(saw_usr1 == 0); 75 kill(pid, SIGUSR1); 76 ASSX(saw_usr1 == 1); 77 78 kill(pid, SIGUSR2); 79 if (sigtest(SIGUSR2, 1)) 80 return (1); 81 kill(pid, SIGUSR2); 82 kill(pid, SIGUSR2); 83 if (sigtest(SIGUSR2, 2)) 84 return (1); 85 86 sigemptyset(&mask); 87 sigaddset(&mask, SIGUSR1); 88 sigaddset(&mask, SIGUSR2); 89 sigprocmask(SIG_BLOCK, &mask, NULL); 90 91 signal(SIGUSR1, SIG_DFL); 92 kill(pid, SIGUSR1); 93 kill(pid, SIGUSR2); 94 95 close(kq); 96 97 return (0); 98 } 99 100