]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
sched: add support for handling exceptions on descriptors
authorMiroslav Lichvar <mlichvar@redhat.com>
Mon, 26 Sep 2016 10:16:42 +0000 (12:16 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 26 Sep 2016 10:40:43 +0000 (12:40 +0200)
sched.c
sched.h

diff --git a/sched.c b/sched.c
index 2cbc29bb8cf0c982580b30740467af1630b152da..a7b83533ebcf5a24f081df9c683a0c90661cbf4c 100644 (file)
--- a/sched.c
+++ b/sched.c
@@ -522,12 +522,25 @@ dispatch_timeouts(struct timespec *now) {
 /* nfd is the number of bits set in all fd_sets */
 
 static void
-dispatch_filehandlers(int nfd, fd_set *read_fds, fd_set *write_fds)
+dispatch_filehandlers(int nfd, fd_set *read_fds, fd_set *write_fds, fd_set *except_fds)
 {
   FileHandlerEntry *ptr;
   int fd;
   
   for (fd = 0; nfd && fd < one_highest_fd; fd++) {
+    if (except_fds && FD_ISSET(fd, except_fds)) {
+      /* This descriptor has an exception, dispatch its handler */
+      ptr = (FileHandlerEntry *)ARR_GetElement(file_handlers, fd);
+      (ptr->handler)(fd, SCH_FILE_EXCEPTION, ptr->arg);
+      nfd--;
+
+      /* Don't try to read from it now */
+      if (read_fds && FD_ISSET(fd, read_fds)) {
+        FD_CLR(fd, read_fds);
+        nfd--;
+      }
+    }
+
     if (read_fds && FD_ISSET(fd, read_fds)) {
       /* This descriptor can be read from, dispatch its handler */
       ptr = (FileHandlerEntry *)ARR_GetElement(file_handlers, fd);
@@ -582,15 +595,15 @@ handle_slew(struct timespec *raw,
 /* ================================================== */
 
 static void
-fill_fd_sets(fd_set **read_fds, fd_set **write_fds)
+fill_fd_sets(fd_set **read_fds, fd_set **write_fds, fd_set **except_fds)
 {
   FileHandlerEntry *handlers;
-  fd_set *rd, *wr;
+  fd_set *rd, *wr, *ex;
   int i, n, events;
 
   n = ARR_GetSize(file_handlers);
   handlers = ARR_GetElements(file_handlers);
-  rd = wr = NULL;
+  rd = wr = ex = NULL;
 
   for (i = 0; i < n; i++) {
     events = handlers[i].events;
@@ -613,12 +626,22 @@ fill_fd_sets(fd_set **read_fds, fd_set **write_fds)
       }
       FD_SET(i, wr);
     }
+
+    if (events & SCH_FILE_EXCEPTION) {
+      if (!ex) {
+        ex = *except_fds;
+        FD_ZERO(ex);
+      }
+      FD_SET(i, ex);
+    }
   }
 
   if (!rd)
     *read_fds = NULL;
   if (!wr)
     *write_fds = NULL;
+  if (!ex)
+    *except_fds = NULL;
 }
 
 /* ================================================== */
@@ -680,7 +703,8 @@ check_current_time(struct timespec *prev_raw, struct timespec *raw, int timeout,
 void
 SCH_MainLoop(void)
 {
-  fd_set read_fds, write_fds, *p_read_fds, *p_write_fds;
+  fd_set read_fds, write_fds, except_fds;
+  fd_set *p_read_fds, *p_write_fds, *p_except_fds;
   int status, errsv;
   struct timeval tv, saved_tv, *ptv;
   struct timespec ts, now, saved_now, cooked;
@@ -712,14 +736,15 @@ SCH_MainLoop(void)
 
     p_read_fds = &read_fds;
     p_write_fds = &write_fds;
-    fill_fd_sets(&p_read_fds, &p_write_fds);
+    p_except_fds = &except_fds;
+    fill_fd_sets(&p_read_fds, &p_write_fds, &p_except_fds);
 
     /* if there are no file descriptors being waited on and no
        timeout set, this is clearly ridiculous, so stop the run */
     if (!ptv && !p_read_fds && !p_write_fds)
       LOG_FATAL(LOGF_Scheduler, "Nothing to do");
 
-    status = select(one_highest_fd, p_read_fds, p_write_fds, NULL, ptv);
+    status = select(one_highest_fd, p_read_fds, p_write_fds, p_except_fds, ptv);
     errsv = errno;
 
     LCL_ReadRawTime(&now);
@@ -741,7 +766,7 @@ SCH_MainLoop(void)
       }
     } else if (status > 0) {
       /* A file descriptor is ready for input or output */
-      dispatch_filehandlers(status, p_read_fds, p_write_fds);
+      dispatch_filehandlers(status, p_read_fds, p_write_fds, p_except_fds);
     } else {
       /* No descriptors readable, timeout must have elapsed.
        Therefore, tv must be non-null */
diff --git a/sched.h b/sched.h
index acadb69f52626fb6631f194711c1c02f08ff4a74..837c914d96bf97c610f781eb7e522bc366eb3c6e 100644 (file)
--- a/sched.h
+++ b/sched.h
@@ -54,6 +54,7 @@ extern void SCH_Finalise(void);
 /* File events */
 #define SCH_FILE_INPUT 1
 #define SCH_FILE_OUTPUT 2
+#define SCH_FILE_EXCEPTION 4
 
 /* Register a handler for when select goes true on a file descriptor */
 extern void SCH_AddFileHandler(int fd, int events, SCH_FileHandler handler, SCH_ArbitraryArgument arg);