gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated: service activation: properly use LISTEN_


From: Admin
Subject: [gnunet] branch master updated: service activation: properly use LISTEN_FDNAMES as per modern systemd specification
Date: Sun, 15 Jun 2025 14:45:20 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 17066b4f3 service activation: properly use LISTEN_FDNAMES as per 
modern systemd specification
17066b4f3 is described below

commit 17066b4f30196866d7056b60c643e37849c3e958
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sun Jun 15 14:27:52 2025 +0200

    service activation: properly use LISTEN_FDNAMES as per modern systemd 
specification
---
 src/lib/util/os_priority.c | 96 +++++++++++++++++++++++++++++++++++-----------
 src/lib/util/service.c     | 86 +++++++++++++++++++++++++++++++----------
 2 files changed, 138 insertions(+), 44 deletions(-)

diff --git a/src/lib/util/os_priority.c b/src/lib/util/os_priority.c
index 35b230a6a..0c02feb5a 100644
--- a/src/lib/util/os_priority.c
+++ b/src/lib/util/os_priority.c
@@ -33,10 +33,11 @@
 #define LOG(kind, ...) GNUNET_log_from (kind, "util-os-priority", __VA_ARGS__)
 
 #define LOG_STRERROR(kind, syscall) \
-  GNUNET_log_from_strerror (kind, "util-os-priority", syscall)
+        GNUNET_log_from_strerror (kind, "util-os-priority", syscall)
 
 #define LOG_STRERROR_FILE(kind, syscall, filename) \
-  GNUNET_log_from_strerror_file (kind, "util-os-priority", syscall, filename)
+        GNUNET_log_from_strerror_file (kind, "util-os-priority", syscall, \
+                                       filename)
 
 #define GNUNET_OS_CONTROL_PIPE "GNUNET_OS_CONTROL_PIPE"
 
@@ -443,8 +444,12 @@ start_process (enum GNUNET_OS_InheritStdioFlags 
std_inheritance,
   if (-1 == ret)
   {
     int eno = errno;
-    LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
-    GNUNET_array_grow (lscp, ls, 0);
+
+    LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
+                  "fork");
+    GNUNET_array_grow (lscp,
+                       ls,
+                       0);
     if (NULL != childpipe_write)
       GNUNET_DISK_file_close (childpipe_write);
     if (0 <= childpipe_read_fd)
@@ -472,49 +477,65 @@ start_process (enum GNUNET_OS_InheritStdioFlags 
std_inheritance,
     /* due to vfork, we must NOT free memory on DARWIN! */
     GNUNET_DISK_file_close (childpipe_write);
 #endif
-    snprintf (fdbuf, 100, "%x", childpipe_read_fd);
-    setenv (GNUNET_OS_CONTROL_PIPE, fdbuf, 1);
+    snprintf (fdbuf,
+              sizeof (fdbuf),
+              "%x",
+              childpipe_read_fd);
+    setenv (GNUNET_OS_CONTROL_PIPE,
+            fdbuf,
+            1);
   }
   else
     unsetenv (GNUNET_OS_CONTROL_PIPE);
   if (NULL != pipe_stdin)
   {
     GNUNET_break (0 == close (fd_stdin_write));
-    if (-1 == dup2 (fd_stdin_read, 0))
-      LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
+    if (-1 == dup2 (fd_stdin_read,
+                    0))
+      LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
+                    "dup2");
     GNUNET_break (0 == close (fd_stdin_read));
   }
   else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_IN))
   {
     GNUNET_break (0 == close (0));
-    open_dev_null (0, O_RDONLY);
+    open_dev_null (0,
+                   O_RDONLY);
   }
   if (NULL != pipe_stdout)
   {
     GNUNET_break (0 == close (fd_stdout_read));
-    if (-1 == dup2 (fd_stdout_write, 1))
-      LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
-    GNUNET_break (0 == close (fd_stdout_write));
+    if (-1 == dup2 (fd_stdout_write,
+                    1))
+      LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
+                    "dup2");
+    GNUNET_break (0 ==
+                  close (fd_stdout_write));
   }
   else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_OUT))
   {
     GNUNET_break (0 == close (1));
-    open_dev_null (1, O_WRONLY);
+    open_dev_null (1,
+                   O_WRONLY);
   }
   if (NULL != pipe_stderr)
   {
     GNUNET_break (0 == close (fd_stderr_read));
-    if (-1 == dup2 (fd_stderr_write, 2))
+    if (-1 == dup2 (fd_stderr_write,
+                    2))
       LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
     GNUNET_break (0 == close (fd_stderr_write));
   }
   else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR))
   {
     GNUNET_break (0 == close (2));
-    open_dev_null (2, O_WRONLY);
+    open_dev_null (2,
+                   O_WRONLY);
   }
   if (NULL != lscp)
   {
+    char *fdnames = GNUNET_strdup ("");
+
     /* read systemd documentation... */
     i = 0;
     tgt = 3;
@@ -539,26 +560,55 @@ start_process (enum GNUNET_OS_InheritStdioFlags 
std_inheritance,
         /* Bury any existing FD, no matter what; they should all be closed
          * on exec anyway and the important ones have been dup'ed away */
         GNUNET_break (0 == close (tgt));
-        GNUNET_assert (-1 != dup2 (lscp[i], tgt));
+        GNUNET_assert (-1 != dup2 (lscp[i],
+                                   tgt));
       }
       /* unset close-on-exec flag */
-      flags = fcntl (tgt, F_GETFD);
+      flags = fcntl (tgt,
+                     F_GETFD);
       GNUNET_assert (flags >= 0);
       flags &= ~FD_CLOEXEC;
       fflush (stderr);
-      (void) fcntl (tgt, F_SETFD, flags);
+      (void) fcntl (tgt,
+                    F_SETFD,
+                    flags);
+      {
+        char *tmp;
+
+        GNUNET_asprintf (&tmp,
+                         "%s:%d",
+                         fdnames,
+                         tgt);
+        GNUNET_free (fdnames);
+        fdnames = tmp;
+      }
       tgt++;
       i++;
     }
-    GNUNET_snprintf (fds, sizeof(fds), "%u", i);
-    setenv ("LISTEN_FDS", fds, 1);
+    GNUNET_snprintf (fds,
+                     sizeof(fds),
+                     "%u",
+                     i);
+    setenv ("LISTEN_FDS",
+            fds,
+            1);
+    if (0 != strlen (fdnames))
+      setenv ("LISTEN_FDNAMES",
+              fdnames + 1, /* skip leading ':' */
+              1);
+    GNUNET_free (fdnames);
   }
 #ifndef DARWIN
   /* due to vfork, we must NOT free memory on DARWIN! */
-  GNUNET_array_grow (lscp, ls, 0);
+  GNUNET_array_grow (lscp,
+                     ls,
+                     0);
 #endif
-  execvp (filename, argv);
-  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
+  execvp (filename,
+          argv);
+  LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_ERROR,
+                     "execvp",
+                     filename);
   _exit (1);
 }
 
diff --git a/src/lib/util/service.c b/src/lib/util/service.c
index ebb09584f..ac78e0f48 100644
--- a/src/lib/util/service.c
+++ b/src/lib/util/service.c
@@ -1480,9 +1480,10 @@ setup_service (const struct GNUNET_OS_ProjectData *pd,
   struct GNUNET_NETWORK_Handle **csocks = NULL;
   struct GNUNET_NETWORK_Handle **lsocks;
   const char *nfds;
+  const char *fdns;
   unsigned int cnt;
   int flags;
-  char dummy[2];
+  char dummy;
 
   if (GNUNET_CONFIGURATION_have_value (sh->cfg,
                                        sh->service_name,
@@ -1506,30 +1507,71 @@ setup_service (const struct GNUNET_OS_ProjectData *pd,
   lsocks = NULL;
   errno = 0;
   if ( (NULL != (nfds = getenv ("LISTEN_FDS"))) &&
-       (1 == sscanf (nfds, "%u%1s", &cnt, dummy)) && (cnt > 0) &&
-       (cnt < FD_SETSIZE) && (cnt + 4 < FD_SETSIZE))
-  {
-    lsocks = GNUNET_new_array (cnt + 1, struct GNUNET_NETWORK_Handle *);
-    while (0 < cnt--)
+       (NULL != (fdns = getenv ("LISTEN_FDNAMES"))) &&
+       (1 == sscanf (nfds,
+                     "%u%c",
+                     &cnt,
+                     &dummy)) &&
+       (cnt > 0) &&
+       (cnt < FD_SETSIZE) )
+  {
+    char *fdnames;
+    unsigned int pos;
+
+    lsocks = GNUNET_new_array (cnt + 1,
+                               struct GNUNET_NETWORK_Handle *);
+    fdnames = GNUNET_strdup (fdns);
+    pos = 0;
+    for (const char *tok = strtok (fdnames,
+                                   ":");
+         NULL != tok;
+         tok = strtok (NULL, ":"))
     {
-      flags = fcntl (3 + cnt, F_GETFD);
-      if ((flags < 0) || (0 != (flags & FD_CLOEXEC)) ||
-          (NULL == (lsocks[cnt] = GNUNET_NETWORK_socket_box_native (3 + cnt))))
+      unsigned int fd;
+
+      if (pos == cnt)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "More than LISTEN_FDS sockets given in LISTEN_FDNAMES\n");
+        break;
+      }
+      if (1 != sscanf (tok,
+                       "%u%c",
+                       &fd,
+                       &dummy))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Malformed socket given in LISTEN_FDNAMES than in 
LISTEN_FDS\n");
+        break;
+      }
+      if (fd >= FD_SETSIZE)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "Socket given in LISTEN_FDNAMES outside of select()able 
range\n");
+        break;
+      }
+      flags = fcntl ((int) fd,
+                     F_GETFD);
+      if ((flags < 0) ||
+          (0 != (flags & FD_CLOEXEC)) ||
+          (NULL == (lsocks[pos] = GNUNET_NETWORK_socket_box_native ((int) 
fd))))
       {
         LOG (GNUNET_ERROR_TYPE_ERROR,
-             _ (
-               "Could not access pre-bound socket %u, will try to bind 
myself\n"),
-             (unsigned int) 3 + cnt);
-        cnt++;
-        while (NULL != lsocks[cnt])
-          GNUNET_break (GNUNET_OK ==
-                        GNUNET_NETWORK_socket_close (lsocks[cnt++]));
-        GNUNET_free (lsocks);
-        lsocks = NULL;
+             "Could not access pre-bound socket %u\n",
+             fd);
         break;
       }
+      pos++;
+    }
+    if (0 == pos)
+    {
+      for (unsigned int i=0; i<cnt; i++)
+        GNUNET_break (GNUNET_OK ==
+                      GNUNET_NETWORK_socket_close (lsocks[i]));
+      GNUNET_free (lsocks);
     }
     unsetenv ("LISTEN_FDS");
+    cnt = pos;
   }
   if ( (0 != (GNUNET_SERVICE_OPTION_CLOSE_LSOCKS & sh->options)) &&
        (NULL != lsocks) )
@@ -1560,7 +1602,10 @@ setup_service (const struct GNUNET_OS_ProjectData *pd,
     socklen_t *addrlens;
     int num;
 
-    num = get_server_addresses (sh->service_name, sh->cfg, &addrs, &addrlens);
+    num = get_server_addresses (sh->service_name,
+                                sh->cfg,
+                                &addrs,
+                                &addrlens);
     if (GNUNET_SYSERR == num)
     {
       GNUNET_free (csocks);
@@ -1593,8 +1638,7 @@ setup_service (const struct GNUNET_OS_ProjectData *pd,
       /* All attempts to bind failed, hard failure */
       GNUNET_log (
         GNUNET_ERROR_TYPE_ERROR,
-        _ (
-          "Could not bind to any of the ports I was supposed to, refusing to 
run!\n"));
+        "Could not bind to any of the ports I was supposed to, refusing to 
run!\n");
       GNUNET_free (csocks);
       return GNUNET_SYSERR;
     }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]