From 0ad0ac6446aa4490800addafd8219f0f2a968c4d Mon Sep 17 00:00:00 2001 From: Florent Bruneau Date: Sun, 12 Oct 2008 23:02:43 +0200 Subject: [PATCH] Switch to libev. Signed-off-by: Florent Bruneau --- common/Makefile | 2 +- common/common.c | 12 --- common/common.h | 5 - common/epoll.c | 83 ---------------- common/epoll.h | 47 ---------- common/rbl.c | 5 +- common/server.c | 188 +++++++++++++++++++++---------------- common/server.h | 28 +++++- pfix-srsd/Makefile | 2 +- pfix-srsd/main-srsd.c | 5 +- postlicyd/Makefile | 2 +- postlicyd/main-postlicyd.c | 10 +- 12 files changed, 139 insertions(+), 250 deletions(-) delete mode 100644 common/epoll.c delete mode 100644 common/epoll.h diff --git a/common/Makefile b/common/Makefile index 3f30e73..6a57421 100644 --- a/common/Makefile +++ b/common/Makefile @@ -32,7 +32,7 @@ LIBS = lib TESTS = tst-trie -lib_SOURCES = str.c buffer.c common.c epoll.c server.c trie.c file.c rbl.c +lib_SOURCES = str.c buffer.c common.c server.c trie.c file.c rbl.c tst-trie_SOURCES = tst-trie.c lib.a all: diff --git a/common/common.c b/common/common.c index 43b2bf2..dc0e194 100644 --- a/common/common.c +++ b/common/common.c @@ -41,9 +41,6 @@ #include "common.h" -sig_atomic_t sigint = false; -sig_atomic_t sighup = false; - bool daemon_process = true; int log_level = LOG_INFO; bool log_syslog = false; @@ -53,15 +50,6 @@ static FILE *pidfile = NULL; void common_sighandler(int sig) { switch (sig) { - case SIGTERM: - case SIGINT: - sigint = true; - return; - - case SIGHUP: - sighup = true; - return; - default: err("Killed (got signal %d)...", sig); exit(-1); diff --git a/common/common.h b/common/common.h index 22299b7..e2f2b3b 100644 --- a/common/common.h +++ b/common/common.h @@ -104,8 +104,6 @@ typedef void (*exitcall_t)(void); #define UNIXERR(fun) err("%s:%d:%s %s: %m", \ __FILE__, __LINE__, __func__, fun) -extern sig_atomic_t sigint; -extern sig_atomic_t sighup; extern int log_level; extern bool log_syslog; @@ -130,9 +128,6 @@ int common_setup(const char* pidfile, bool unsafe, const char* runas_user, static inline void common_startup(void) { signal(SIGPIPE, SIG_IGN); - signal(SIGINT, &common_sighandler); - signal(SIGTERM, &common_sighandler); - signal(SIGHUP, &common_sighandler); signal(SIGSEGV, &common_sighandler); } diff --git a/common/epoll.c b/common/epoll.c deleted file mode 100644 index 896fc2c..0000000 --- a/common/epoll.c +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************/ -/* pfixtools: a collection of postfix related tools */ -/* ~~~~~~~~~ */ -/* ________________________________________________________________________ */ -/* */ -/* Redistribution and use in source and binary forms, with or without */ -/* modification, are permitted provided that the following conditions */ -/* are met: */ -/* */ -/* 1. Redistributions of source code must retain the above copyright */ -/* notice, this list of conditions and the following disclaimer. */ -/* 2. Redistributions in binary form must reproduce the above copyright */ -/* notice, this list of conditions and the following disclaimer in the */ -/* documentation and/or other materials provided with the distribution. */ -/* 3. The names of its contributors may not be used to endorse or promote */ -/* products derived from this software without specific prior written */ -/* permission. */ -/* */ -/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ -/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ -/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ -/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ -/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ -/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ -/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ -/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ -/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ -/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ -/* THE POSSIBILITY OF SUCH DAMAGE. */ -/******************************************************************************/ - -/* - * Copyright © 2007 Pierre Habouzit - */ - -#include "epoll.h" - -static int epollfd = -1; - -static int epoll_initialize(void) -{ - epollfd = epoll_create(128); - return epollfd < 0 ? -1 : 0; -} - -static void epoll_shutdown(void) -{ - close(epollfd); -} - -module_init(epoll_initialize); -module_exit(epoll_shutdown); - -void epoll_register(int fd, uint32_t events, void *ptr) -{ - struct epoll_event evt = { .events = events, .data.ptr = ptr }; - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &evt)) { - UNIXERR("epoll_ctl"); - abort(); - } -} - -void epoll_modify(int fd, uint32_t events, void *ptr) -{ - struct epoll_event evt = { .events = events, .data.ptr = ptr }; - if (epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &evt)) { - UNIXERR("epoll_ctl"); - abort(); - } -} - -void epoll_unregister(int fd) -{ - if (epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL)) { - UNIXERR("epoll_ctl"); - abort(); - } -} - -int epoll_select(struct epoll_event *events, int maxevents, int timeout) -{ - return epoll_wait(epollfd, events, maxevents, timeout); -} diff --git a/common/epoll.h b/common/epoll.h deleted file mode 100644 index fdc2665..0000000 --- a/common/epoll.h +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************/ -/* pfixtools: a collection of postfix related tools */ -/* ~~~~~~~~~ */ -/* ________________________________________________________________________ */ -/* */ -/* Redistribution and use in source and binary forms, with or without */ -/* modification, are permitted provided that the following conditions */ -/* are met: */ -/* */ -/* 1. Redistributions of source code must retain the above copyright */ -/* notice, this list of conditions and the following disclaimer. */ -/* 2. Redistributions in binary form must reproduce the above copyright */ -/* notice, this list of conditions and the following disclaimer in the */ -/* documentation and/or other materials provided with the distribution. */ -/* 3. The names of its contributors may not be used to endorse or promote */ -/* products derived from this software without specific prior written */ -/* permission. */ -/* */ -/* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND */ -/* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE */ -/* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR */ -/* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS */ -/* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */ -/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF */ -/* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS */ -/* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN */ -/* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) */ -/* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF */ -/* THE POSSIBILITY OF SUCH DAMAGE. */ -/******************************************************************************/ - -/* - * Copyright © 2007 Pierre Habouzit - */ - -#ifndef PFIXTOOLS_EPOLL_H -#define PFIXTOOLS_EPOLL_H - -#include -#include "common.h" - -void epoll_register(int fd, uint32_t events, void *ptr); -void epoll_modify(int fd, uint32_t events, void *ptr); -void epoll_unregister(int fd); -int epoll_select(struct epoll_event *events, int maxevents, int timeout); - -#endif diff --git a/common/rbl.c b/common/rbl.c index 4f8c23f..e7c79fb 100644 --- a/common/rbl.c +++ b/common/rbl.c @@ -36,7 +36,6 @@ #include #include #include "array.h" -#include "epoll.h" #include "server.h" #include "rbl.h" @@ -126,11 +125,11 @@ static int rbl_handler(server_t *event, void *config) { int retval = 0; debug("rbl_handler called: ub_fd triggered"); - epoll_modify(event->fd, 0, event); + server_none(event); if ((retval = ub_process(ctx)) != 0) { err("error in DNS resolution: %s", ub_strerror(retval)); } - epoll_modify(event->fd, EPOLLIN, event); + server_ro(event); return 0; } diff --git a/common/server.c b/common/server.c index 838e9f7..d529896 100644 --- a/common/server.c +++ b/common/server.c @@ -40,6 +40,13 @@ static PA(server_t) listeners = ARRAY_INIT; static PA(server_t) server_pool = ARRAY_INIT; +struct ev_loop *global_loop = NULL; +static start_client_t client_start = NULL; +static delete_client_t client_delete = NULL; +static run_client_t client_run = NULL; +static refresh_t config_refresh = NULL; +static void *config_ptr = NULL; + static server_t* server_new(void) { server_t* server = p_new(server_t, 1); @@ -49,9 +56,8 @@ static server_t* server_new(void) static void server_wipe(server_t *server) { - server->listener = false; if (server->fd >= 0) { - epoll_unregister(server->fd); + ev_io_stop(global_loop, &server->io); close(server->fd); server->fd = -1; } @@ -85,78 +91,115 @@ void server_release(server_t *server) array_add(server_pool, server); } +static int server_init(void) +{ + global_loop = ev_default_loop(0); + return 0; +} + static void server_shutdown(void) { - printf("Server shutdown"); array_deep_wipe(listeners, server_delete); array_deep_wipe(server_pool, server_delete); } - +module_init(server_init); module_exit(server_shutdown); -int start_server(int port, start_listener_t starter, delete_client_t deleter) +static void client_cb(EV_P_ struct ev_io *w, int events) +{ + server_t *server = (server_t*)w; + + debug("Entering client_cb for %p, %d (%d | %d)", w, events, EV_WRITE, EV_READ); + + if (events & EV_WRITE && server->obuf.len) { + if (buffer_write(&server->obuf, server->fd) < 0) { + server_release(server); + return; + } + if (!server->obuf.len) { + ev_io_set(&server->io, server->fd, EV_READ); + } + } + + if (events & EV_READ) { + if (server->run(server, config_ptr) < 0) { + server_release(server); + return; + } + } +} + +static int start_client(server_t *server, start_client_t starter, + run_client_t runner, delete_client_t deleter) { - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_addr = { htonl(INADDR_LOOPBACK) }, - }; server_t *tmp; void* data = NULL; int sock; - addr.sin_port = htons(port); - sock = tcp_listen_nonblock((const struct sockaddr *)&addr, sizeof(addr)); + sock = accept_nonblock(server->fd); if (sock < 0) { + UNIXERR("accept"); return -1; } if (starter) { - data = starter(); - if (data == NULL) { - close(sock); - return -1; - } + data = starter(server); + if (data == NULL) { + close(sock); + return -1; + } } tmp = server_acquire(); tmp->fd = sock; - tmp->listener = true; tmp->data = data; - tmp->run = NULL; + tmp->run = runner; tmp->clear_data = deleter; - epoll_register(sock, EPOLLIN, tmp); - array_add(listeners, tmp); + ev_io_init(&tmp->io, client_cb, tmp->fd, EV_READ); + ev_io_start(global_loop, &tmp->io); return 0; } -static int start_client(server_t *server, start_client_t starter, - run_client_t runner, delete_client_t deleter) +static void server_cb(EV_P_ struct ev_io *w, int events) { + server_t *server = (server_t*)w; + if (start_client(server, client_start, client_run, client_delete) != 0) { + ev_unloop(EV_A_ EVUNLOOP_ALL); + } +} + +int start_server(int port, start_listener_t starter, delete_client_t deleter) +{ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr = { htonl(INADDR_LOOPBACK) }, + }; server_t *tmp; void* data = NULL; int sock; - sock = accept_nonblock(server->fd); + addr.sin_port = htons(port); + sock = tcp_listen_nonblock((const struct sockaddr *)&addr, sizeof(addr)); if (sock < 0) { - UNIXERR("accept"); return -1; } if (starter) { - data = starter(server); - if (data == NULL) { - close(sock); - return -1; - } + data = starter(); + if (data == NULL) { + close(sock); + return -1; + } } tmp = server_acquire(); - tmp->listener = false; tmp->fd = sock; tmp->data = data; - tmp->run = runner; + tmp->run = NULL; tmp->clear_data = deleter; - epoll_register(sock, EPOLLIN, tmp); + ev_io_init(&tmp->io, server_cb, tmp->fd, EV_READ); + ev_io_start(global_loop, &tmp->io); + array_add(listeners, tmp); return 0; } @@ -167,68 +210,51 @@ server_t *server_register(int fd, run_client_t runner, void *data) } server_t *tmp = server_acquire(); - tmp->listener = false; tmp->fd = fd; tmp->data = data; tmp->run = runner; tmp->clear_data = NULL; - epoll_register(fd, EPOLLIN, tmp); + ev_io_init(&tmp->io, client_cb, tmp->fd, EV_READ); + ev_io_start(global_loop, &tmp->io); return tmp; } +static void refresh_cb(EV_P_ struct ev_signal *w, int event) +{ + if (!config_refresh(config_ptr)) { + ev_unloop(EV_A_ EVUNLOOP_ALL); + } +} + +static void exit_cb(EV_P_ struct ev_signal *w, int event) +{ + ev_unloop(EV_A_ EVUNLOOP_ALL); +} + int server_loop(start_client_t starter, delete_client_t deleter, run_client_t runner, refresh_t refresh, void* config) { - info("entering processing loop"); - while (!sigint) { - struct epoll_event evts[1024]; - int n; - - if (sighup && refresh) { - sighup = false; - info("refreshing..."); - if (!refresh(config)) { - crit("error while refreshing configuration"); - return EXIT_FAILURE; - } - info("refresh done, processing loop restarts"); - } + struct ev_signal ev_sighup; + struct ev_signal ev_sigint; + struct ev_signal ev_sigterm; - n = epoll_select(evts, countof(evts), -1); - if (n < 0) { - if (errno != EAGAIN && errno != EINTR) { - UNIXERR("epoll_wait"); - return EXIT_FAILURE; - } - continue; - } + client_start = starter; + client_delete = deleter; + client_run = runner; + config_refresh = refresh; + config_ptr = config; - while (--n >= 0) { - server_t *d = evts[n].data.ptr; - - if (d->listener) { - (void)start_client(d, starter, runner, deleter); - continue; - } - - if ((evts[n].events & EPOLLOUT) && d->obuf.len) { - if (buffer_write(&d->obuf, d->fd) < 0) { - server_release(d); - continue; - } - if (!d->obuf.len) { - epoll_modify(d->fd, EPOLLIN, d); - } - } - - if (evts[n].events & EPOLLIN) { - if (d->run(d, config) < 0) { - server_release(d); - } - continue; - } - } + if (refresh != NULL) { + ev_signal_init(&ev_sighup, refresh_cb, SIGHUP); + ev_signal_start(global_loop, &ev_sighup); } + ev_signal_init(&ev_sigint, exit_cb, SIGINT); + ev_signal_start(global_loop, &ev_sigint); + ev_signal_init(&ev_sigterm, exit_cb, SIGTERM); + ev_signal_start(global_loop, &ev_sigterm); + + info("entering processing loop"); + ev_loop(global_loop, 0); info("exit requested"); return EXIT_SUCCESS; } diff --git a/common/server.h b/common/server.h index 33d7157..e31b4ef 100644 --- a/common/server.h +++ b/common/server.h @@ -36,22 +36,21 @@ #ifndef PFIXTOOLS_SERVER_H #define PFIXTOOLS_SERVER_H +#include #include "buffer.h" typedef struct server_t server_t; -#define INVALID_EVENT (NULL) - typedef void *(*start_listener_t)(void); typedef void (*delete_client_t)(void*); typedef void *(*start_client_t)(server_t*); typedef int (*run_client_t)(server_t*, void*); typedef bool (*refresh_t)(void*); -typedef bool (*event_handler_t)(server_t *, void*); -struct server_t { - unsigned listener : 1; +extern struct ev_loop *global_loop; +struct server_t { + struct ev_io io; int fd; buffer_t ibuf; @@ -68,6 +67,25 @@ int start_server(int port, start_listener_t starter, delete_client_t deleter); server_t *server_register(int fd, run_client_t runner, void *data); void server_release(server_t *server); +static inline void server_none(server_t *server) +{ + ev_io_stop(global_loop, &server->io); +} + +static inline void server_rw(server_t *server) +{ + ev_io_stop(global_loop, &server->io); + ev_io_set(&server->io, server->fd, EV_READ | EV_WRITE); + ev_io_start(global_loop, &server->io); +} + +static inline void server_ro(server_t *server) +{ + ev_io_stop(global_loop, &server->io); + ev_io_set(&server->io, server->fd, EV_READ); + ev_io_start(global_loop, &server->io); +} + int server_loop(start_client_t starter, delete_client_t deleter, run_client_t runner, refresh_t refresh, void *config); diff --git a/pfix-srsd/Makefile b/pfix-srsd/Makefile index 0be9e82..fbe3c60 100644 --- a/pfix-srsd/Makefile +++ b/pfix-srsd/Makefile @@ -32,7 +32,7 @@ PROGRAMS = pfix-srsd pfix-srsd_SOURCES = main-srsd.c ../common/lib.a -pfix-srsd_LIBADD = -lsrs2 +pfix-srsd_LIBADD = -lsrs2 -lev all: diff --git a/pfix-srsd/main-srsd.c b/pfix-srsd/main-srsd.c index 037a458..440e56f 100644 --- a/pfix-srsd/main-srsd.c +++ b/pfix-srsd/main-srsd.c @@ -38,7 +38,6 @@ #include -#include "epoll.h" #include "mem.h" #include "buffer.h" #include "server.h" @@ -127,7 +126,7 @@ int process_srs(server_t *srsd, void* vconfig) return -1; } if (srsd->obuf.len) { - epoll_modify(srsd->fd, EPOLLIN | EPOLLOUT, srsd); + server_rw(srsd); } return 0; } @@ -175,7 +174,7 @@ int process_srs(server_t *srsd, void* vconfig) buffer_consume(&srsd->ibuf, nl - srsd->ibuf.data); } if (srsd->obuf.len) { - epoll_modify(srsd->fd, EPOLLIN | EPOLLOUT, srsd); + server_rw(srsd); } return 0; } diff --git a/postlicyd/Makefile b/postlicyd/Makefile index 104155c..81d2ac2 100644 --- a/postlicyd/Makefile +++ b/postlicyd/Makefile @@ -43,7 +43,7 @@ UB_LIBS = -lunbound FILTERS = iplist.c greylist.c strlist.c match.c postlicyd_SOURCES = main-postlicyd.c ../common/lib.a filter.c config.c query.c $(FILTERS) $(GENERATED) -postlicyd_LIBADD = $(UB_LIBS) $(TC_LIBS) +postlicyd_LIBADD = $(UB_LIBS) $(TC_LIBS) -lev tst-rbl_SOURCES = tst-rbl.c ../common/lib.a filter.c config.c query.c iplist.c $(GENERATED) diff --git a/postlicyd/main-postlicyd.c b/postlicyd/main-postlicyd.c index fa31a1e..5975167 100644 --- a/postlicyd/main-postlicyd.c +++ b/postlicyd/main-postlicyd.c @@ -38,7 +38,6 @@ #include "buffer.h" #include "common.h" -#include "epoll.h" #include "policy_tokens.h" #include "server.h" #include "config.h" @@ -74,7 +73,6 @@ static void query_stopper(void *data) static bool config_refresh(void *mconfig) { if (filter_running > 0) { - sighup = true; sleep(1); return true; } @@ -105,7 +103,7 @@ static void policy_answer(server_t *pcy, const char *message) } buffer_addstr(&pcy->obuf, "\n\n"); buffer_consume(&pcy->ibuf, query->eoq - pcy->ibuf.data); - epoll_modify(pcy->fd, EPOLLIN | EPOLLOUT, pcy); + server_rw(pcy); } static const filter_t *next_filter(server_t *pcy, const filter_t *filter, @@ -175,10 +173,6 @@ static bool policy_process(server_t *pcy, const config_t *mconfig) static int policy_run(server_t *pcy, void* vconfig) { - if (sighup) { - return 0; - } - int search_offs = MAX(0, (int)(pcy->ibuf.len - 1)); int nb = buffer_read(&pcy->ibuf, pcy->fd, -1); const char *eoq; @@ -205,7 +199,7 @@ static int policy_run(server_t *pcy, void* vconfig) if (!query_parse(pcy->data, pcy->ibuf.data)) return -1; query->eoq = eoq + strlen("\n\n"); - epoll_modify(pcy->fd, 0, pcy); + server_none(pcy); return policy_process(pcy, mconfig) ? 0 : -1; } -- 2.20.1