From cde61dd0b59b0f3f3b3afefafd045f8d75b32975 Mon Sep 17 00:00:00 2001 From: Pierre Habouzit Date: Mon, 5 Feb 2007 01:40:28 +0100 Subject: [PATCH] implement the event loop, add a stopper. Signed-off-by: Pierre Habouzit --- job.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++- job.h | 4 +++ postfix.c | 10 +++++-- postlicyd.c | 29 ++++++++++++++++++ 4 files changed, 125 insertions(+), 3 deletions(-) diff --git a/job.c b/job.c index 23cd3d5..5216e65 100644 --- a/job.c +++ b/job.c @@ -33,11 +33,16 @@ * Copyright © 2007 Pierre Habouzit */ +#include #include +#include #include +#include +#include #include #include #include +#include #include #ifndef EPOLLRDHUP @@ -52,7 +57,8 @@ #include "job.h" -static int epollfd; +static int epollfd = -1; +static bool sigint = false; static void job_wipe(job_t *job) { @@ -86,6 +92,7 @@ static job_t *job_register_fd(job_t *job) } if (epoll_ctl(epollfd, EPOLL_CTL_ADD, job->fd, &event) < 0) { + syslog(LOG_ERR, "epoll_ctl error: %m"); job->error = true; job_release(&job); } @@ -119,10 +126,12 @@ job_t *job_accept(job_t *listener, int state) job_t *res; if ((sock = accept(listener->fd, NULL, 0)) < 0) { + syslog(LOG_ERR, "accept error: %m"); return NULL; } if (fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK)) { + syslog(LOG_ERR, "fcntl error: %m"); return NULL; } @@ -133,3 +142,77 @@ job_t *job_accept(job_t *listener, int state) res->stop = listener->stop; return job_register_fd(res); } + +static void job_handler(int sig) +{ + static time_t lastintr = 0; + time_t now = time(NULL); + + switch (sig) { + case SIGINT: + if (sigint) { + if (now - lastintr >= 1) + break; + } else { + lastintr = now; + sigint = true; + } + return; + + case SIGTERM: + break; + + default: + return; + } + + syslog(LOG_ERR, "Killed..."); + exit(-1); +} + +void job_initialize(void) +{ + signal(SIGPIPE, SIG_IGN); + signal(SIGINT, &job_handler); + signal(SIGTERM, &job_handler); + + epollfd = epoll_create(128); + if (epollfd < 0) { + syslog(LOG_ERR, "epoll_create error: %m"); + exit(EX_OSERR); + } +} + +void job_loop(void) +{ + while (!sigint) { + struct epoll_event events[FD_SETSIZE]; + int todo = epoll_wait(epollfd, events, countof(events), -1); + + if (todo < 0) { + if (errno == EAGAIN || errno == EINTR) + continue; + syslog(LOG_ERR, "epoll_wait error: %m"); + exit(EX_OSERR); + } + + while (todo) { + job_t *job = events[--todo].data.ptr; + + assert (job->process); + job->process(job); + + if (job->error || job->done) { + job_release(&job); + } + } + } +} + +void job_shutdown(void) +{ + if (epollfd >= 0) { + close(epollfd); + epollfd = -1; + } +} diff --git a/job.h b/job.h index 95638c9..36e5c0d 100644 --- a/job.h +++ b/job.h @@ -84,4 +84,8 @@ void job_release(job_t **job); void job_update_state(job_t *job, int state); job_t *job_accept(job_t *listener, int state); +void job_initialize(void); +void job_loop(void); +void job_shutdown(void); + #endif diff --git a/postfix.c b/postfix.c index 533955e..1ecd9f2 100644 --- a/postfix.c +++ b/postfix.c @@ -35,6 +35,7 @@ #include #include +#include #include #include "job.h" @@ -88,7 +89,9 @@ void postfix_process(job_t *job) case JOB_WRITE: nb = write(job->fd, job->jdata->obuf.data, job->jdata->obuf.len); if (nb < 0) { - job->error = errno != EINTR && errno != EAGAIN; + if ((job->error = errno != EINTR && errno != EAGAIN)) { + syslog(LOG_ERR, "unexpected problem on the socket: %m"); + } return; } @@ -103,10 +106,13 @@ void postfix_process(job_t *job) case JOB_READ: nb = buffer_read(&job->jdata->ibuf, job->fd, -1); if (nb < 0) { - job->error = errno != EINTR && errno != EAGAIN; + if ((job->error = errno != EINTR && errno != EAGAIN)) { + syslog(LOG_ERR, "unexpected problem on the socket: %m"); + } return; } if (nb == 0) { + syslog(LOG_ERR, "unexpected eof"); job->error = true; return; } diff --git a/postlicyd.c b/postlicyd.c index d980d20..03675ad 100644 --- a/postlicyd.c +++ b/postlicyd.c @@ -33,7 +33,36 @@ * Copyright © 2006 Pierre Habouzit */ +#include +#include +#include +#include + +#include "job.h" + +bool cleanexit = false; + +void shutdown(void) +{ + syslog(LOG_INFO, cleanexit ? "Stopping..." : "Unclean exit..."); + job_shutdown(); + closelog(); +} + int main(void) { + if (atexit(shutdown)) { + fputs("Cannot hook my atexit function, quitting !\n", stderr); + return EX_CONFIG; + } + + openlog("postlicyd", LOG_PID, LOG_MAIL); + job_initialize(); + syslog(LOG_INFO, "Starting..."); + + job_loop(); + + cleanexit = true; + shutdown(); return 0; } -- 2.20.1