INN commit: trunk (10 files)

INN Commit rra at isc.org
Sun Jan 17 21:41:25 UTC 2021


    Date: Sunday, January 17, 2021 @ 13:41:25
  Author: iulius
Revision: 10518

Add support for systemd socket activation

Thanks to Marco d'Itri for that new feature!

Modified:
  trunk/doc/FAQ
  trunk/doc/pod/inn.conf.pod
  trunk/doc/pod/innd.pod
  trunk/doc/pod/install.pod
  trunk/doc/pod/news.pod
  trunk/innd/Makefile
  trunk/innd/cc.c
  trunk/innd/chan.c
  trunk/innd/innd.h
  trunk/innd/rc.c

----------------------+
 doc/FAQ              |    2 -
 doc/pod/inn.conf.pod |    4 ++
 doc/pod/innd.pod     |    4 ++
 doc/pod/install.pod  |    8 ++---
 doc/pod/news.pod     |    2 -
 innd/Makefile        |   20 ++++++++------
 innd/cc.c            |   36 ++++++++++++++++++++++++--
 innd/chan.c          |   25 ++++++++++++++++++
 innd/innd.h          |    1 
 innd/rc.c            |   67 +++++++++++++++++++++++++++++++++++++++++++++++--
 10 files changed, 150 insertions(+), 19 deletions(-)

Modified: doc/FAQ
===================================================================
--- doc/FAQ	2021-01-17 21:36:59 UTC (rev 10517)
+++ doc/FAQ	2021-01-17 21:41:25 UTC (rev 10518)
@@ -463,7 +463,7 @@
     readers and the expiry process;
 
   - ovdb, which stores overview information into a Berkeley DB database,
-    whose ddevelopment pace has stalled these last years.  This method
+    whose development pace has stalled these last years.  This method
     is fast and very robust, but may require more disk space, unless
     compression is enabled.  Overview data is fetched one article at a
     time, which makes this method a bit slower than ovsqlite for readers;

Modified: doc/pod/inn.conf.pod
===================================================================
--- doc/pod/inn.conf.pod	2021-01-17 21:36:59 UTC (rev 10517)
+++ doc/pod/inn.conf.pod	2021-01-17 21:41:25 UTC (rev 10518)
@@ -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:36:59 UTC (rev 10517)
+++ doc/pod/innd.pod	2021-01-17 21:41:25 UTC (rev 10518)
@@ -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:36:59 UTC (rev 10517)
+++ doc/pod/install.pod	2021-01-17 21:41:25 UTC (rev 10518)
@@ -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:36:59 UTC (rev 10517)
+++ doc/pod/news.pod	2021-01-17 21:41:25 UTC (rev 10518)
@@ -70,7 +70,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: innd/Makefile
===================================================================
--- innd/Makefile	2021-01-17 21:36:59 UTC (rev 10517)
+++ innd/Makefile	2021-01-17 21:41:25 UTC (rev 10518)
@@ -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:36:59 UTC (rev 10517)
+++ innd/cc.c	2021-01-17 21:41:25 UTC (rev 10518)
@@ -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"
@@ -1329,6 +1330,8 @@
     char	*innd;
     char	*p;
     int		i;
+    const char  *s;
+    int         count;
     int         status;
 
     if (CCargv == NULL)
@@ -1354,8 +1357,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:36:59 UTC (rev 10517)
+++ innd/chan.c	2021-01-17 21:41:25 UTC (rev 10518)
@@ -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:36:59 UTC (rev 10517)
+++ innd/innd.h	2021-01-17 21:41:25 UTC (rev 10518)
@@ -723,6 +723,7 @@
 extern void		ARTreject(Reject_type, CHANNEL *);
 
 extern bool		CHANsleeping(CHANNEL *cp);
+extern bool             CHANsystemdsa(CHANNEL *cp);
 extern CHANNEL      *	CHANcreate(int fd, enum channel_type type,
 				   enum channel_state state,
 				   innd_callback_func reader,

Modified: innd/rc.c
===================================================================
--- innd/rc.c	2021-01-17 21:36:59 UTC (rev 10517)
+++ innd/rc.c	2021-01-17 21:41:25 UTC (rev 10518)
@@ -1735,7 +1735,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
@@ -1817,8 +1875,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;
 	}



More information about the inn-committers mailing list