implement the event loop, add a stopper.
authorPierre Habouzit <madcoder@debian.org>
Mon, 5 Feb 2007 00:40:28 +0000 (01:40 +0100)
committerPierre Habouzit <madcoder@debian.org>
Mon, 5 Feb 2007 00:40:28 +0000 (01:40 +0100)
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
job.c
job.h
postfix.c
postlicyd.c

diff --git a/job.c b/job.c
index 23cd3d5..5216e65 100644 (file)
--- a/job.c
+++ b/job.c
  * Copyright © 2007 Pierre Habouzit
  */
 
+#include <errno.h>
 #include <fcntl.h>
+#include <signal.h>
 #include <stdbool.h>
+#include <syslog.h>
+#include <sysexits.h>
 #include <sys/epoll.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <time.h>
 #include <unistd.h>
 
 #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 (file)
--- 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
index 533955e..1ecd9f2 100644 (file)
--- a/postfix.c
+++ b/postfix.c
@@ -35,6 +35,7 @@
 
 #include <errno.h>
 #include <stdbool.h>
+#include <syslog.h>
 #include <unistd.h>
 
 #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;
         }
index d980d20..03675ad 100644 (file)
  * Copyright © 2006 Pierre Habouzit
  */
 
+#include <stdbool.h>
+#include <stdio.h>
+#include <sysexits.h>
+#include <syslog.h>
+
+#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;
 }