1171169Smlaier/* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */ 2171169Smlaier 3171169Smlaier/* 4171169Smlaier * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu> 5171169Smlaier * All rights reserved. 6171169Smlaier * 7171169Smlaier * Redistribution and use in source and binary forms, with or without 8171169Smlaier * modification, are permitted provided that the following conditions 9171169Smlaier * are met: 10171169Smlaier * 1. Redistributions of source code must retain the above copyright 11171169Smlaier * notice, this list of conditions and the following disclaimer. 12171169Smlaier * 2. Redistributions in binary form must reproduce the above copyright 13171169Smlaier * notice, this list of conditions and the following disclaimer in the 14171169Smlaier * documentation and/or other materials provided with the distribution. 15171169Smlaier * 3. The name of the author may not be used to endorse or promote products 16171169Smlaier * derived from this software without specific prior written permission. 17171169Smlaier * 18171169Smlaier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19171169Smlaier * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20171169Smlaier * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21171169Smlaier * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22171169Smlaier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23171169Smlaier * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24171169Smlaier * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25171169Smlaier * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26171169Smlaier * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27171169Smlaier * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28171169Smlaier */ 29171169Smlaier#ifdef HAVE_CONFIG_H 30171169Smlaier#include "config.h" 31171169Smlaier#endif 32171169Smlaier 33171169Smlaier#include <sys/types.h> 34171169Smlaier#ifdef HAVE_SYS_TIME_H 35171169Smlaier#include <sys/time.h> 36171169Smlaier#else 37171169Smlaier#include <sys/_time.h> 38171169Smlaier#endif 39171169Smlaier#include <sys/queue.h> 40171169Smlaier#include <sys/socket.h> 41171169Smlaier#include <signal.h> 42171169Smlaier#include <stdio.h> 43171169Smlaier#include <stdlib.h> 44171169Smlaier#include <string.h> 45171169Smlaier#include <unistd.h> 46171169Smlaier#include <errno.h> 47171169Smlaier#ifdef HAVE_FCNTL_H 48171169Smlaier#include <fcntl.h> 49171169Smlaier#endif 50171169Smlaier 51171169Smlaier#include "event.h" 52171169Smlaier#include "evsignal.h" 53171169Smlaier#include "log.h" 54171169Smlaier 55171169Smlaierextern struct event_list signalqueue; 56171169Smlaier 57171169Smlaierstatic sig_atomic_t evsigcaught[NSIG]; 58171169Smlaiervolatile sig_atomic_t evsignal_caught = 0; 59171169Smlaier 60171169Smlaierstatic struct event ev_signal; 61171169Smlaierstatic int ev_signal_pair[2]; 62171169Smlaierstatic int ev_signal_added; 63171169Smlaier 64171169Smlaierstatic void evsignal_handler(int sig); 65171169Smlaier 66171169Smlaier/* Callback for when the signal handler write a byte to our signaling socket */ 67171169Smlaierstatic void 68171169Smlaierevsignal_cb(int fd, short what, void *arg) 69171169Smlaier{ 70171169Smlaier static char signals[100]; 71171169Smlaier struct event *ev = arg; 72171169Smlaier ssize_t n; 73171169Smlaier 74171169Smlaier n = read(fd, signals, sizeof(signals)); 75171169Smlaier if (n == -1) 76171169Smlaier event_err(1, "%s: read", __func__); 77171169Smlaier event_add(ev, NULL); 78171169Smlaier} 79171169Smlaier 80171169Smlaier#ifdef HAVE_SETFD 81171169Smlaier#define FD_CLOSEONEXEC(x) do { \ 82171169Smlaier if (fcntl(x, F_SETFD, 1) == -1) \ 83171169Smlaier event_warn("fcntl(%d, F_SETFD)", x); \ 84171169Smlaier} while (0) 85171169Smlaier#else 86171169Smlaier#define FD_CLOSEONEXEC(x) 87171169Smlaier#endif 88171169Smlaier 89171169Smlaiervoid 90171169Smlaierevsignal_init(void) 91171169Smlaier{ 92171169Smlaier /* 93171169Smlaier * Our signal handler is going to write to one end of the socket 94171169Smlaier * pair to wake up our event loop. The event loop then scans for 95171169Smlaier * signals that got delivered. 96171169Smlaier */ 97171169Smlaier if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1) 98171169Smlaier event_err(1, "%s: socketpair", __func__); 99171169Smlaier 100171169Smlaier FD_CLOSEONEXEC(ev_signal_pair[0]); 101171169Smlaier FD_CLOSEONEXEC(ev_signal_pair[1]); 102171169Smlaier 103171169Smlaier fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK); 104171169Smlaier 105171169Smlaier event_set(&ev_signal, ev_signal_pair[1], EV_READ, 106171169Smlaier evsignal_cb, &ev_signal); 107171169Smlaier ev_signal.ev_flags |= EVLIST_INTERNAL; 108171169Smlaier} 109171169Smlaier 110171169Smlaierint 111171169Smlaierevsignal_add(struct event *ev) 112171169Smlaier{ 113171169Smlaier int evsignal; 114171169Smlaier struct sigaction sa; 115171169Smlaier 116171169Smlaier if (ev->ev_events & (EV_READ|EV_WRITE)) 117171169Smlaier event_errx(1, "%s: EV_SIGNAL incompatible use", __func__); 118171169Smlaier evsignal = EVENT_SIGNAL(ev); 119171169Smlaier 120171169Smlaier memset(&sa, 0, sizeof(sa)); 121171169Smlaier sa.sa_handler = evsignal_handler; 122171169Smlaier sigfillset(&sa.sa_mask); 123171169Smlaier sa.sa_flags |= SA_RESTART; 124171169Smlaier 125171169Smlaier if (sigaction(evsignal, &sa, NULL) == -1) 126171169Smlaier return (-1); 127171169Smlaier 128171169Smlaier if (!ev_signal_added) { 129171169Smlaier ev_signal_added = 1; 130171169Smlaier event_add(&ev_signal, NULL); 131171169Smlaier } 132171169Smlaier 133171169Smlaier return (0); 134171169Smlaier} 135171169Smlaier 136171169Smlaier/* 137171169Smlaier * Nothing to be done here. 138171169Smlaier */ 139171169Smlaier 140171169Smlaierint 141171169Smlaierevsignal_del(struct event *ev) 142171169Smlaier{ 143171169Smlaier int evsignal; 144171169Smlaier 145171169Smlaier evsignal = EVENT_SIGNAL(ev); 146171169Smlaier 147171169Smlaier return (sigaction(EVENT_SIGNAL(ev),(struct sigaction *)SIG_DFL, NULL)); 148171169Smlaier} 149171169Smlaier 150171169Smlaierstatic void 151171169Smlaierevsignal_handler(int sig) 152171169Smlaier{ 153171169Smlaier int save_errno = errno; 154171169Smlaier 155171169Smlaier evsigcaught[sig]++; 156171169Smlaier evsignal_caught = 1; 157171169Smlaier 158171169Smlaier /* Wake up our notification mechanism */ 159171169Smlaier write(ev_signal_pair[0], "a", 1); 160171169Smlaier errno = save_errno; 161171169Smlaier} 162171169Smlaier 163171169Smlaiervoid 164171169Smlaierevsignal_process(void) 165171169Smlaier{ 166171169Smlaier struct event *ev; 167171169Smlaier sig_atomic_t ncalls; 168171169Smlaier 169171169Smlaier evsignal_caught = 0; 170171169Smlaier TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) { 171171169Smlaier ncalls = evsigcaught[EVENT_SIGNAL(ev)]; 172171169Smlaier if (ncalls) { 173171169Smlaier if (!(ev->ev_events & EV_PERSIST)) 174171169Smlaier event_del(ev); 175171169Smlaier event_active(ev, EV_SIGNAL, ncalls); 176171169Smlaier evsigcaught[EVENT_SIGNAL(ev)] = 0; 177171169Smlaier } 178171169Smlaier } 179171169Smlaier} 180171169Smlaier 181