167ecd4f3SMax Laier /* $OpenBSD: select.c,v 1.2 2002/06/25 15:50:15 mickey Exp $ */
267ecd4f3SMax Laier
367ecd4f3SMax Laier /*
467ecd4f3SMax Laier * Copyright 2000-2002 Niels Provos <provos@citi.umich.edu>
567ecd4f3SMax Laier * All rights reserved.
667ecd4f3SMax Laier *
767ecd4f3SMax Laier * Redistribution and use in source and binary forms, with or without
867ecd4f3SMax Laier * modification, are permitted provided that the following conditions
967ecd4f3SMax Laier * are met:
1067ecd4f3SMax Laier * 1. Redistributions of source code must retain the above copyright
1167ecd4f3SMax Laier * notice, this list of conditions and the following disclaimer.
1267ecd4f3SMax Laier * 2. Redistributions in binary form must reproduce the above copyright
1367ecd4f3SMax Laier * notice, this list of conditions and the following disclaimer in the
1467ecd4f3SMax Laier * documentation and/or other materials provided with the distribution.
1567ecd4f3SMax Laier * 3. The name of the author may not be used to endorse or promote products
1667ecd4f3SMax Laier * derived from this software without specific prior written permission.
1767ecd4f3SMax Laier *
1867ecd4f3SMax Laier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1967ecd4f3SMax Laier * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2067ecd4f3SMax Laier * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2167ecd4f3SMax Laier * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2267ecd4f3SMax Laier * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2367ecd4f3SMax Laier * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2467ecd4f3SMax Laier * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2567ecd4f3SMax Laier * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2667ecd4f3SMax Laier * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2767ecd4f3SMax Laier * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2867ecd4f3SMax Laier */
2967ecd4f3SMax Laier #ifdef HAVE_CONFIG_H
3067ecd4f3SMax Laier #include "config.h"
3167ecd4f3SMax Laier #endif
3267ecd4f3SMax Laier
3367ecd4f3SMax Laier #include <sys/types.h>
3467ecd4f3SMax Laier #ifdef HAVE_SYS_TIME_H
3567ecd4f3SMax Laier #include <sys/time.h>
3667ecd4f3SMax Laier #else
3767ecd4f3SMax Laier #include <sys/_time.h>
3867ecd4f3SMax Laier #endif
3967ecd4f3SMax Laier #include <sys/queue.h>
4067ecd4f3SMax Laier #include <sys/socket.h>
4167ecd4f3SMax Laier #include <signal.h>
4267ecd4f3SMax Laier #include <stdio.h>
4367ecd4f3SMax Laier #include <stdlib.h>
4467ecd4f3SMax Laier #include <string.h>
4567ecd4f3SMax Laier #include <unistd.h>
4667ecd4f3SMax Laier #include <errno.h>
4767ecd4f3SMax Laier #ifdef HAVE_FCNTL_H
4867ecd4f3SMax Laier #include <fcntl.h>
4967ecd4f3SMax Laier #endif
5067ecd4f3SMax Laier
5167ecd4f3SMax Laier #include "event.h"
5267ecd4f3SMax Laier #include "evsignal.h"
5367ecd4f3SMax Laier #include "log.h"
5467ecd4f3SMax Laier
5567ecd4f3SMax Laier extern struct event_list signalqueue;
5667ecd4f3SMax Laier
5767ecd4f3SMax Laier static sig_atomic_t evsigcaught[NSIG];
5867ecd4f3SMax Laier volatile sig_atomic_t evsignal_caught = 0;
5967ecd4f3SMax Laier
6067ecd4f3SMax Laier static struct event ev_signal;
6167ecd4f3SMax Laier static int ev_signal_pair[2];
6267ecd4f3SMax Laier static int ev_signal_added;
6367ecd4f3SMax Laier
6467ecd4f3SMax Laier static void evsignal_handler(int sig);
6567ecd4f3SMax Laier
6667ecd4f3SMax Laier /* Callback for when the signal handler write a byte to our signaling socket */
6767ecd4f3SMax Laier static void
evsignal_cb(int fd,short what,void * arg)6867ecd4f3SMax Laier evsignal_cb(int fd, short what, void *arg)
6967ecd4f3SMax Laier {
7067ecd4f3SMax Laier static char signals[100];
7167ecd4f3SMax Laier struct event *ev = arg;
7267ecd4f3SMax Laier ssize_t n;
7367ecd4f3SMax Laier
7467ecd4f3SMax Laier n = read(fd, signals, sizeof(signals));
7567ecd4f3SMax Laier if (n == -1)
7667ecd4f3SMax Laier event_err(1, "%s: read", __func__);
7767ecd4f3SMax Laier event_add(ev, NULL);
7867ecd4f3SMax Laier }
7967ecd4f3SMax Laier
8067ecd4f3SMax Laier #ifdef HAVE_SETFD
8167ecd4f3SMax Laier #define FD_CLOSEONEXEC(x) do { \
8267ecd4f3SMax Laier if (fcntl(x, F_SETFD, 1) == -1) \
8367ecd4f3SMax Laier event_warn("fcntl(%d, F_SETFD)", x); \
8467ecd4f3SMax Laier } while (0)
8567ecd4f3SMax Laier #else
8667ecd4f3SMax Laier #define FD_CLOSEONEXEC(x)
8767ecd4f3SMax Laier #endif
8867ecd4f3SMax Laier
8967ecd4f3SMax Laier void
evsignal_init(void)9067ecd4f3SMax Laier evsignal_init(void)
9167ecd4f3SMax Laier {
9267ecd4f3SMax Laier /*
9367ecd4f3SMax Laier * Our signal handler is going to write to one end of the socket
9467ecd4f3SMax Laier * pair to wake up our event loop. The event loop then scans for
9567ecd4f3SMax Laier * signals that got delivered.
9667ecd4f3SMax Laier */
9767ecd4f3SMax Laier if (socketpair(AF_UNIX, SOCK_STREAM, 0, ev_signal_pair) == -1)
9867ecd4f3SMax Laier event_err(1, "%s: socketpair", __func__);
9967ecd4f3SMax Laier
10067ecd4f3SMax Laier FD_CLOSEONEXEC(ev_signal_pair[0]);
10167ecd4f3SMax Laier FD_CLOSEONEXEC(ev_signal_pair[1]);
10267ecd4f3SMax Laier
10367ecd4f3SMax Laier fcntl(ev_signal_pair[0], F_SETFL, O_NONBLOCK);
10467ecd4f3SMax Laier
10567ecd4f3SMax Laier event_set(&ev_signal, ev_signal_pair[1], EV_READ,
10667ecd4f3SMax Laier evsignal_cb, &ev_signal);
10767ecd4f3SMax Laier ev_signal.ev_flags |= EVLIST_INTERNAL;
10867ecd4f3SMax Laier }
10967ecd4f3SMax Laier
11067ecd4f3SMax Laier int
evsignal_add(struct event * ev)11167ecd4f3SMax Laier evsignal_add(struct event *ev)
11267ecd4f3SMax Laier {
11367ecd4f3SMax Laier int evsignal;
11467ecd4f3SMax Laier struct sigaction sa;
11567ecd4f3SMax Laier
11667ecd4f3SMax Laier if (ev->ev_events & (EV_READ|EV_WRITE))
11767ecd4f3SMax Laier event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
11867ecd4f3SMax Laier evsignal = EVENT_SIGNAL(ev);
11967ecd4f3SMax Laier
12067ecd4f3SMax Laier memset(&sa, 0, sizeof(sa));
12167ecd4f3SMax Laier sa.sa_handler = evsignal_handler;
12267ecd4f3SMax Laier sigfillset(&sa.sa_mask);
12367ecd4f3SMax Laier sa.sa_flags |= SA_RESTART;
12467ecd4f3SMax Laier
12567ecd4f3SMax Laier if (sigaction(evsignal, &sa, NULL) == -1)
12667ecd4f3SMax Laier return (-1);
12767ecd4f3SMax Laier
12867ecd4f3SMax Laier if (!ev_signal_added) {
12967ecd4f3SMax Laier ev_signal_added = 1;
13067ecd4f3SMax Laier event_add(&ev_signal, NULL);
13167ecd4f3SMax Laier }
13267ecd4f3SMax Laier
13367ecd4f3SMax Laier return (0);
13467ecd4f3SMax Laier }
13567ecd4f3SMax Laier
13667ecd4f3SMax Laier /*
13767ecd4f3SMax Laier * Nothing to be done here.
13867ecd4f3SMax Laier */
13967ecd4f3SMax Laier
14067ecd4f3SMax Laier int
evsignal_del(struct event * ev)14167ecd4f3SMax Laier evsignal_del(struct event *ev)
14267ecd4f3SMax Laier {
14367ecd4f3SMax Laier int evsignal;
14467ecd4f3SMax Laier
14567ecd4f3SMax Laier evsignal = EVENT_SIGNAL(ev);
14667ecd4f3SMax Laier
147*b488428eSJohn Baldwin return (sigaction(evsignal, (struct sigaction *)SIG_DFL, NULL));
14867ecd4f3SMax Laier }
14967ecd4f3SMax Laier
15067ecd4f3SMax Laier static void
evsignal_handler(int sig)15167ecd4f3SMax Laier evsignal_handler(int sig)
15267ecd4f3SMax Laier {
15367ecd4f3SMax Laier int save_errno = errno;
15467ecd4f3SMax Laier
15567ecd4f3SMax Laier evsigcaught[sig]++;
15667ecd4f3SMax Laier evsignal_caught = 1;
15767ecd4f3SMax Laier
15867ecd4f3SMax Laier /* Wake up our notification mechanism */
15967ecd4f3SMax Laier write(ev_signal_pair[0], "a", 1);
16067ecd4f3SMax Laier errno = save_errno;
16167ecd4f3SMax Laier }
16267ecd4f3SMax Laier
16367ecd4f3SMax Laier void
evsignal_process(void)16467ecd4f3SMax Laier evsignal_process(void)
16567ecd4f3SMax Laier {
16667ecd4f3SMax Laier struct event *ev;
16767ecd4f3SMax Laier sig_atomic_t ncalls;
16867ecd4f3SMax Laier
16967ecd4f3SMax Laier evsignal_caught = 0;
17067ecd4f3SMax Laier TAILQ_FOREACH(ev, &signalqueue, ev_signal_next) {
17167ecd4f3SMax Laier ncalls = evsigcaught[EVENT_SIGNAL(ev)];
17267ecd4f3SMax Laier if (ncalls) {
17367ecd4f3SMax Laier if (!(ev->ev_events & EV_PERSIST))
17467ecd4f3SMax Laier event_del(ev);
17567ecd4f3SMax Laier event_active(ev, EV_SIGNAL, ncalls);
17667ecd4f3SMax Laier evsigcaught[EVENT_SIGNAL(ev)] = 0;
17767ecd4f3SMax Laier }
17867ecd4f3SMax Laier }
17967ecd4f3SMax Laier }
18067ecd4f3SMax Laier
181