INN commit: branches/2.6 (12 files)

INN Commit rra at isc.org
Sun Jan 17 21:52:00 UTC 2021


    Date: Sunday, January 17, 2021 @ 13:52:00
  Author: iulius
Revision: 10523

Add support for systemd socket activation

Thanks to Marco d'Itri for that new feature!

Modified:
  branches/2.6/doc/pod/inn.conf.pod
  branches/2.6/doc/pod/innd.pod
  branches/2.6/doc/pod/install.pod
  branches/2.6/doc/pod/news.pod
  branches/2.6/include/portable/sd-daemon.h
  branches/2.6/innd/Makefile
  branches/2.6/innd/cc.c
  branches/2.6/innd/chan.c
  branches/2.6/innd/innd.h
  branches/2.6/innd/rc.c
  branches/2.6/tests/lib/fdflag-t.c
  branches/2.6/tests/runtests.c

------------------------------+
 doc/pod/inn.conf.pod         |    4 ++
 doc/pod/innd.pod             |    4 ++
 doc/pod/install.pod          |    8 ++--
 doc/pod/news.pod             |    2 -
 include/portable/sd-daemon.h |    7 ++--
 innd/Makefile                |   20 ++++++------
 innd/cc.c                    |   36 ++++++++++++++++++++--
 innd/chan.c                  |   25 +++++++++++++++
 innd/innd.h                  |   11 +++---
 innd/rc.c                    |   67 +++++++++++++++++++++++++++++++++++++++--
 tests/lib/fdflag-t.c         |    4 +-
 tests/runtests.c             |   10 +++---
 12 files changed, 167 insertions(+), 31 deletions(-)

Modified: doc/pod/inn.conf.pod
===================================================================
--- doc/pod/inn.conf.pod	2021-01-17 21:49:28 UTC (rev 10522)
+++ doc/pod/inn.conf.pod	2021-01-17 21:52:00 UTC (rev 10523)
@@ -185,6 +185,8 @@
 INND_BIND_ADDRESS environment variable, if set, overrides this setting.
 The default value is unset.
 
+This parameter has no effect when systemd socket activation is used.
+
 =item I<bindaddress6>
 
 Like I<bindaddress> but for IPv6 sockets. If only one of the I<bindaddress>
@@ -198,6 +200,8 @@
 Note that you will generally need to put double quotes ("") around this
 value if you set it, since IPv6 addresses contain colons.
 
+This parameter has no effect when systemd socket activation is used.
+
 =item I<dontrejectfiltered>
 
 Normally innd(8) rejects incoming articles when directed to do so by

Modified: doc/pod/innd.pod
===================================================================
--- doc/pod/innd.pod	2021-01-17 21:49:28 UTC (rev 10522)
+++ doc/pod/innd.pod	2021-01-17 21:52:00 UTC (rev 10523)
@@ -77,6 +77,8 @@
 F<inn.conf> and may cause changes in whether INN binds to an IPv6 address
 as well.  See inn.conf(5) for more details and also the B<-6> flag for B<innd>.
 
+This option has no effect when systemd socket activation is used.
+
 =item B<-6> I<address>
 
 Only applies when INN has been built with IPv6 support.  Normally B<innd>
@@ -89,6 +91,8 @@
 F<inn.conf> and may cause changes in whether INN binds to an IPv4 address
 as well.  See inn.conf(5) for more details and also the B<-4> flag for B<innd>.
 
+This option has no effect when systemd socket activation is used.
+
 =item B<-a>
 
 By default, if a host connects to B<innd> but is not listed in

Modified: doc/pod/install.pod
===================================================================
--- doc/pod/install.pod	2021-01-17 21:49:28 UTC (rev 10522)
+++ doc/pod/install.pod	2021-01-17 21:52:00 UTC (rev 10523)
@@ -139,10 +139,10 @@
 
 =item *
 
-If you want to use systemd notifications, you'll need to have
-B<pkg-config> and B<libsystemd> (along with its F<libsystemd.pc>
-configuration) installed so that this feature is enabled at configure
-time.
+If you want to use systemd notifications and socket activation,
+you'll need to have B<pkg-config> and B<libsystemd> (along with its
+F<libsystemd.pc> configuration) installed so that these features are
+enabled at configure time.
 
 =item *
 

Modified: doc/pod/news.pod
===================================================================
--- doc/pod/news.pod	2021-01-17 21:49:28 UTC (rev 10522)
+++ doc/pod/news.pod	2021-01-17 21:52:00 UTC (rev 10523)
@@ -51,7 +51,7 @@
 
 =item *
 
-Added preliminary support for systemd notifications.  Use of more
+Added support for systemd notifications and socket activation.  Use of more
 features provided by systemd, including more notifications, will come
 in future releases.  Thanks to Marco d'Itri for this first systemd
 integration into INN.

Modified: include/portable/sd-daemon.h
===================================================================
--- include/portable/sd-daemon.h	2021-01-17 21:49:28 UTC (rev 10522)
+++ include/portable/sd-daemon.h	2021-01-17 21:52:00 UTC (rev 10523)
@@ -29,9 +29,10 @@
 #ifdef HAVE_SD_NOTIFY
 #    include <systemd/sd-daemon.h>
 #else
-#    define SD_LISTEN_FDS_START 3
-#    define sd_listen_fds(u)    0
-#    define sd_notify(u, s)     0
+#    define SD_LISTEN_FDS_START        3
+#    define sd_is_socket(fd, f, t, l)  0
+#    define sd_listen_fds(u)           0
+#    define sd_notify(u, s)            0
 #endif
 
 #endif /* !PORTABLE_SD_DAEMON_H */

Modified: innd/Makefile
===================================================================
--- innd/Makefile	2021-01-17 21:49:28 UTC (rev 10522)
+++ innd/Makefile	2021-01-17 21:52:00 UTC (rev 10523)
@@ -91,15 +91,17 @@
   ../include/inn/defines.h ../include/inn/options.h ../include/clibrary.h \
   ../include/config.h ../include/inn/macros.h \
   ../include/portable/stdbool.h ../include/portable/socket-unix.h \
-  ../include/inn/innconf.h ../include/inn/qio.h innd.h \
-  ../include/portable/macros.h ../include/portable/sd-daemon.h \
-  ../include/portable/socket.h ../include/portable/getaddrinfo.h \
-  ../include/portable/getnameinfo.h ../include/inn/buffer.h \
-  ../include/inn/history.h ../include/inn/messages.h \
-  ../include/inn/timer.h ../include/inn/libinn.h ../include/inn/concat.h \
-  ../include/inn/xmalloc.h ../include/inn/xwrite.h ../include/inn/nntp.h \
-  ../include/inn/paths.h ../include/inn/storage.h ../include/inn/options.h \
-  ../include/inn/vector.h ../include/inn/inndcomm.h ../include/innperl.h
+  ../include/inn/fdflag.h ../include/inn/portable-socket.h \
+  ../include/inn/portable-getaddrinfo.h \
+  ../include/inn/portable-getnameinfo.h ../include/inn/innconf.h \
+  ../include/inn/qio.h innd.h ../include/portable/macros.h \
+  ../include/portable/sd-daemon.h ../include/portable/socket.h \
+  ../include/inn/buffer.h ../include/inn/history.h \
+  ../include/inn/messages.h ../include/inn/timer.h ../include/inn/libinn.h \
+  ../include/inn/concat.h ../include/inn/xmalloc.h ../include/inn/xwrite.h \
+  ../include/inn/nntp.h ../include/inn/paths.h ../include/inn/storage.h \
+  ../include/inn/options.h ../include/inn/vector.h \
+  ../include/inn/inndcomm.h ../include/innperl.h
 chan.o: chan.c ../include/config.h ../include/inn/defines.h \
   ../include/inn/system.h ../include/inn/macros.h \
   ../include/inn/portable-macros.h ../include/inn/portable-stdbool.h \

Modified: innd/cc.c
===================================================================
--- innd/cc.c	2021-01-17 21:49:28 UTC (rev 10522)
+++ innd/cc.c	2021-01-17 21:52:00 UTC (rev 10523)
@@ -19,6 +19,7 @@
 # include "portable/socket-unix.h"
 #endif
 
+#include "inn/fdflag.h"
 #include "inn/innconf.h"
 #include "inn/qio.h"
 #include "innd.h"
@@ -1321,6 +1322,8 @@
     char	*innd;
     char	*p;
     int		i;
+    const char  *s;
+    int         count;
     int         status;
 
     if (CCargv == NULL)
@@ -1346,8 +1349,37 @@
     if (status < 0)
         warn("cannot notify systemd of reloading: %s", strerror(-status));
 
-    /* Close all fds to protect possible fd leaking accross successive innds. */
-    for (i=3; i<30; i++)
+    /* Restore the systemd variables which were backed up in RCsetup()
+       if socket activation was set. */
+    s = getenv("INN_BACKUP_LISTEN_FDS");
+    if (s != NULL) {
+        if (setenv("LISTEN_FDS", s, true) != 0)
+            die("setenv failed for LISTEN_FDS");
+        if (unsetenv("INN_BACKUP_LISTEN_FDS") != 0)
+            die("unsetenv failed for INN_BACKUP_LISTEN_FDS");
+    }
+    s = getenv("INN_BACKUP_LISTEN_PID");
+    if (s != NULL) {
+        if (setenv("LISTEN_PID", s, true) != 0)
+            die("setenv failed for LISTEN_PID");
+        if (unsetenv("INN_BACKUP_LISTEN_PID") != 0)
+            die("unsetenv failed for INN_BACKUP_LISTEN_PID");
+    }
+
+    /* Clear the close-on-exec flag on the socket activation file descriptors.
+       This is needed because we need to pass them to the new innd process
+       and sd_listen_fds(), which was called in RCsetup(), set it on all
+       passed file descriptors. */
+    s = getenv("INN_SD_LISTEN_FDS_COUNT");
+    if (s == NULL)
+        count = 0;
+    else
+        count = atoi(s);
+    for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + count; i++)
+        fdflag_close_exec(i, false);
+
+    /* Close all fds to protect possible fd leaking across successive innds. */
+    for (i = SD_LISTEN_FDS_START + count; i < 30; i++)
         close(i);
 
     execv(CCargv[0], CCargv);

Modified: innd/chan.c
===================================================================
--- innd/chan.c	2021-01-17 21:49:28 UTC (rev 10522)
+++ innd/chan.c	2021-01-17 21:52:00 UTC (rev 10523)
@@ -78,6 +78,29 @@
 
 
 /*
+**  Returns true if socket activation is used and the channel given as
+**  as argument is used for socket activation.  Returns false otherwise.
+*/
+bool
+CHANsystemdsa(CHANNEL *cp)
+{
+    const char *s;
+    int count;
+
+    s = getenv("INN_SD_LISTEN_FDS_COUNT");
+    if (s == NULL)
+        return false;
+
+    count = atoi(s);
+
+    if (cp->fd >= SD_LISTEN_FDS_START && cp->fd < SD_LISTEN_FDS_START + count)
+        return true;
+
+    return false;
+}
+
+
+/*
 **  Tear down our world.  Free all of the allocated channels and clear all
 **  global state data.  This function can also be used to initialize the
 **  channels structure to a known empty state.
@@ -98,6 +121,8 @@
     if (channels.table != NULL) {
         cp = channels.table;
         for (i = channels.table_size; --i >= 0; cp++) {
+            if (CHANsystemdsa(cp))
+                continue;
             if (cp->Type != CTfree)
                 CHANclose(cp, CHANname(cp));
             if (cp->In.data)

Modified: innd/innd.h
===================================================================
--- innd/innd.h	2021-01-17 21:49:28 UTC (rev 10522)
+++ innd/innd.h	2021-01-17 21:52:00 UTC (rev 10523)
@@ -723,11 +723,12 @@
 extern void		ARTreject(Reject_type, CHANNEL *);
 
 extern bool		CHANsleeping(CHANNEL *cp);
-extern CHANNEL      *	CHANcreate(int fd, enum channel_type Type,
-				   enum channel_state State,
-				   innd_callback_func Reader,
-				   innd_callback_func WriteDone);
-extern CHANNEL      *	CHANiter(int *cp, enum channel_type Type);
+extern bool             CHANsystemdsa(CHANNEL *cp);
+extern CHANNEL      *	CHANcreate(int fd, enum channel_type type,
+				   enum channel_state state,
+				   innd_callback_func reader,
+				   innd_callback_func write_done);
+extern CHANNEL      *	CHANiter(int *ip, enum channel_type type);
 extern CHANNEL      *	CHANfromdescriptor(int fd);
 extern char	    *   CHANname(CHANNEL *cp);
 extern int		CHANreadtext(CHANNEL *cp);

Modified: innd/rc.c
===================================================================
--- innd/rc.c	2021-01-17 21:49:28 UTC (rev 10522)
+++ innd/rc.c	2021-01-17 21:52:00 UTC (rev 10523)
@@ -1733,7 +1733,65 @@
     unsigned int count, i, start;
     int *fds;
     bool okay;
+    const char *s;
 
+    /* If systemd socket activation is used, backup its environment variables,
+       which are unset by sd_listen_fds(), to be able to restore them later in
+       CCxexec() before starting a new innd process. */
+    s = getenv("LISTEN_FDS");
+    if (s != NULL) {
+        if (setenv("INN_BACKUP_LISTEN_FDS", s, true) != 0)
+            die("setenv failed for INN_BACKUP_LISTEN_FDS");
+    }
+    s = getenv("LISTEN_PID");
+    if (s != NULL) {
+        if (setenv("INN_BACKUP_LISTEN_PID", s, true) != 0)
+            die("setenv failed for INN_BACKUP_LISTEN_PID");
+    }
+
+    /* Ignore any configured ports if socket activation is being used. */
+    count = sd_listen_fds(true);
+    if (count > 0) {
+        char *p;
+
+        xasprintf(&p, "%u", count);
+        if (setenv("INN_SD_LISTEN_FDS_COUNT", p, true) != 0)
+            die("setenv failed for INN_SD_LISTEN_FDS_COUNT");
+
+        free(p);
+
+        /* Make sure that the RCchan array is of the appropriate size. */
+        if (chanlimit == 0) {
+            chanlimit = count;
+            RCchan = xmalloc(chanlimit * sizeof(CHANNEL *));
+            start = 0;
+        } else {
+            for (start = 0; start < chanlimit; start++) {
+                if (RCchan[start] == NULL)
+                    break;
+                 if (chanlimit - start < count) {
+                     chanlimit += count - (chanlimit - start);
+                     RCchan = xrealloc(RCchan, chanlimit * sizeof(CHANNEL *));
+                 }
+            }
+        }
+
+        for (i = SD_LISTEN_FDS_START; i < SD_LISTEN_FDS_START + count; i++) {
+            if (sd_is_socket(i, AF_UNSPEC, SOCK_STREAM, 1) <= 0)
+                die("SERVER can't use socket-activated non-AF_INET socket %u",
+                    i);
+            rc = CHANcreate(i, CTremconn, CSwaiting, RCreader, RCwritedone);
+            notice("%s rcsetup %s", LogName, CHANname(rc));
+            RCHANadd(rc);
+            RCchan[start + i - SD_LISTEN_FDS_START] = rc;
+        }
+
+        /* Get the list of hosts we handle. */
+        RCreadlist();
+
+        return;
+    }
+
     /* If neither bindaddress or bindaddress6 are set, we have to do this the
        hard way.  Either way, allocate an fds array to hold the file
        descriptors.  Two is probably always sufficient, but we can't tell for
@@ -1815,8 +1873,13 @@
     unsigned int j;
 
     for (j = 0 ; j < chanlimit ; j++) {
-	if (RCchan[j] != NULL) {
-	    CHANclose(RCchan[j], CHANname(RCchan[j]));
+        if (RCchan[j] != NULL) {
+            /* Do not close the listening sockets if socket activation is being
+               used because they need to be passed as-is by CCxexec() to the
+               next innd process. */
+            if (CHANsystemdsa(RCchan[j]))
+                continue;
+            CHANclose(RCchan[j], CHANname(RCchan[j]));
 	} else {
 	    break;
 	}

Modified: tests/lib/fdflag-t.c
===================================================================
--- tests/lib/fdflag-t.c	2021-01-17 21:49:28 UTC (rev 10522)
+++ tests/lib/fdflag-t.c	2021-01-17 21:52:00 UTC (rev 10523)
@@ -116,8 +116,10 @@
         if (read(data, buffer, sizeof(buffer)) < (ssize_t) sizeof(buffer))
             sysbail("read failed");
         fclose(stderr);
+        /* Use of echo 'ok 7' does not display it on Solaris 11. */
         execlp("sh", "sh", "-c",
-               "printf 'not ' >&8; echo ok 7; echo 'ok 8' >&9", (char *) 0);
+               "printf 'not ' >&8; printf 'ok 7\n'; echo 'ok 8' >&9",
+               (char *) 0);
         sysbail("exec failed");
     }
     waitpid(child, NULL, 0);

Modified: tests/runtests.c
===================================================================
--- tests/runtests.c	2021-01-17 21:49:28 UTC (rev 10522)
+++ tests/runtests.c	2021-01-17 21:52:00 UTC (rev 10523)
@@ -1140,11 +1140,13 @@
      * retrieve the exit status, and pass that information to test_analyze()
      * for eventual output.
      */
-    while (fgets(buffer, sizeof(buffer), output))
-        if (verbose)
-            printf("%s", buffer);
+    if (!ts->aborted) {
+        while (fgets(buffer, sizeof(buffer), output))
+            if (verbose)
+                printf("%s", buffer);
+    }
     fclose(output);
-    child = waitpid(testpid, &ts->status, 0);
+    child = waitpid(testpid, &ts->status, WNOHANG);
     if (child == (pid_t) -1) {
         if (!ts->reported) {
             puts("ABORTED");



More information about the inn-committers mailing list