gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r11907 - in gnunet: . src/arm src/include src/util


From: gnunet
Subject: [GNUnet-SVN] r11907 - in gnunet: . src/arm src/include src/util
Date: Wed, 23 Jun 2010 16:23:50 +0200

Author: grothoff
Date: 2010-06-23 16:23:50 +0200 (Wed, 23 Jun 2010)
New Revision: 11907

Modified:
   gnunet/ChangeLog
   gnunet/src/arm/arm_api.c
   gnunet/src/arm/do_start_process.c
   gnunet/src/arm/gnunet-service-arm.c
   gnunet/src/arm/gnunet-service-arm.h
   gnunet/src/arm/gnunet-service-arm_interceptor.c
   gnunet/src/include/gnunet_network_lib.h
   gnunet/src/include/gnunet_os_lib.h
   gnunet/src/util/os_priority.c
Log:
listen socket passing support for ARM

Modified: gnunet/ChangeLog
===================================================================
--- gnunet/ChangeLog    2010-06-23 14:23:25 UTC (rev 11906)
+++ gnunet/ChangeLog    2010-06-23 14:23:50 UTC (rev 11907)
@@ -1,3 +1,8 @@
+Wed Jun 23 16:34:38 CEST 2010
+       Added support for systemd-compatible passing of listen-sockets
+       by ARM to services as well as systemd compatibility for 
gnunet-service-arm
+       itself.  At least for non-MINGW systems this should work.
+
 Sat Jun  5 18:08:39 CEST 2010
        Added support for UNIX domain sockets, code also defaults to
        them when available.

Modified: gnunet/src/arm/arm_api.c
===================================================================
--- gnunet/src/arm/arm_api.c    2010-06-23 14:23:25 UTC (rev 11906)
+++ gnunet/src/arm/arm_api.c    2010-06-23 14:23:50 UTC (rev 11907)
@@ -434,7 +434,8 @@
       GNUNET_free (lopostfix);
       return;
     }
-  pid = do_start_process (loprefix,
+  pid = do_start_process (NULL,
+                         loprefix,
                          binary,
                          "-c", config,
 #if DEBUG_ARM

Modified: gnunet/src/arm/do_start_process.c
===================================================================
--- gnunet/src/arm/do_start_process.c   2010-06-23 14:23:25 UTC (rev 11906)
+++ gnunet/src/arm/do_start_process.c   2010-06-23 14:23:50 UTC (rev 11907)
@@ -7,12 +7,14 @@
  * limitation that it does NOT allow passing command line arguments
  * with spaces to the new process.
  *
+ * @param lsocks array of listen sockets to dup starting at fd3 
(systemd-style), or NULL
  * @param first_arg first argument for argv (may be an empty string)
  * @param ... more arguments, NULL terminated
  * @return PID of the started process, -1 on error
  */
 static pid_t
-do_start_process (const char *first_arg, ...)
+do_start_process (const int *lsocks,
+                 const char *first_arg, ...)
 {
   va_list ap;
   char **argv;
@@ -86,7 +88,7 @@
   while (NULL != (arg = (va_arg (ap, const char*))));
   va_end (ap);
   argv[argv_size] = NULL;
-  pid = GNUNET_OS_start_process_v (argv[0], argv);
+  pid = GNUNET_OS_start_process_v (lsocks, argv[0], argv);
   while (argv_size > 0)
     GNUNET_free (argv[--argv_size]);
   GNUNET_free (argv);

Modified: gnunet/src/arm/gnunet-service-arm.c
===================================================================
--- gnunet/src/arm/gnunet-service-arm.c 2010-06-23 14:23:25 UTC (rev 11906)
+++ gnunet/src/arm/gnunet-service-arm.c 2010-06-23 14:23:50 UTC (rev 11907)
@@ -344,7 +344,8 @@
  * @param sl identifies service to start
  */
 static void
-start_process (struct ServiceList *sl)
+start_process (struct ServiceList *sl,
+              const int *lsocks)
 {
   char *loprefix;
   char *options;
@@ -415,14 +416,16 @@
              sl->name, sl->binary, sl->config);
 #endif
   if (GNUNET_YES == use_debug)
-    sl->pid = do_start_process (loprefix,
+    sl->pid = do_start_process (lsocks,
+                               loprefix,                               
                                sl->binary,
                                "-c", sl->config,
                                "-L", "DEBUG",
                                options,
                                NULL);
   else
-    sl->pid = do_start_process (loprefix,
+    sl->pid = do_start_process (lsocks,
+                               loprefix,
                                sl->binary,
                                "-c", sl->config,
                                options,
@@ -442,9 +445,13 @@
  *
  * @param client who is asking for this
  * @param servicename name of the service to start
+ * @param lsocks -1 terminated list of listen sockets to pass (systemd style), 
or NULL
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error
  */
-void
-start_service (struct GNUNET_SERVER_Client *client, const char *servicename)
+int
+start_service (struct GNUNET_SERVER_Client *client, 
+              const char *servicename,
+              const int *lsocks)
 {
   struct ServiceList *sl;
   char *binary;
@@ -457,7 +464,7 @@
                  _("ARM is shutting down, service `%s' not started.\n"),
                  servicename);
       signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
-      return;
+      return GNUNET_SYSERR;
     }
   sl = find_name (servicename);
   if (sl != NULL)
@@ -467,7 +474,7 @@
       sl->next = running;
       running = sl;
       signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP);
-      return;
+      return GNUNET_SYSERR;
     }
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_string (cfg,
@@ -477,7 +484,7 @@
                  _("Binary implementing service `%s' not known!\n"),
                  servicename);
       signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
-      return;
+      return GNUNET_SYSERR;
     }
   if ((GNUNET_OK !=
        GNUNET_CONFIGURATION_get_value_filename (cfg,
@@ -492,7 +499,7 @@
       signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
       GNUNET_free (binary);
       GNUNET_free_non_null (config);
-      return;
+      return GNUNET_SYSERR;
     }
   (void) stop_listening (servicename);
   sl = GNUNET_malloc (sizeof (struct ServiceList));
@@ -505,9 +512,10 @@
   sl->restartAt = GNUNET_TIME_UNIT_FOREVER_ABS;
 
   running = sl;
-  start_process (sl);
+  start_process (sl, lsocks);
   if (NULL != client)
     signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP);
+  return GNUNET_OK;
 }
 
 
@@ -610,7 +618,7 @@
       GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
       return;
     }
-  start_service (client, servicename);
+  start_service (client, servicename, NULL);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
@@ -776,7 +784,7 @@
            {
              GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                          _("Restarting service `%s'.\n"), pos->name);
-             start_process (pos);
+             start_process (pos, NULL);
            }
          else
            {
@@ -1071,7 +1079,7 @@
          pos = strtok (defaultservices, " ");
          while (pos != NULL)
            {
-             start_service (NULL, pos);
+             start_service (NULL, pos, NULL);
              pos = strtok (NULL, " ");
            }
        }

Modified: gnunet/src/arm/gnunet-service-arm.h
===================================================================
--- gnunet/src/arm/gnunet-service-arm.h 2010-06-23 14:23:25 UTC (rev 11906)
+++ gnunet/src/arm/gnunet-service-arm.h 2010-06-23 14:23:50 UTC (rev 11907)
@@ -27,8 +27,17 @@
 #ifndef GNUNET_SERVICE_ARM__H
 #define GNUNET_SERVICE_ARM__H
 
-void start_service (struct GNUNET_SERVER_Client *client,
-                   const char *servicename);
+/**
+ * Start the specified service.
+ *
+ * @param client who is asking for this
+ * @param servicename name of the service to start 
+ * @param lsocks -1 terminated list of listen sockets to pass (systemd style), 
or NULL
+ * @return GNUNET_OK on success
+ */
+int start_service (struct GNUNET_SERVER_Client *client,
+                  const char *servicename,
+                  const int *lsocks);
 
 /**
  * Stop listening for connections to a service.

Modified: gnunet/src/arm/gnunet-service-arm_interceptor.c
===================================================================
--- gnunet/src/arm/gnunet-service-arm_interceptor.c     2010-06-23 14:23:25 UTC 
(rev 11906)
+++ gnunet/src/arm/gnunet-service-arm_interceptor.c     2010-06-23 14:23:50 UTC 
(rev 11907)
@@ -847,7 +847,6 @@
   return ret;
 }
 
-
 /**
  * First connection has come to the listening socket associated with the 
service,
  * create the service in order to relay the incoming connection to it
@@ -856,14 +855,15 @@
  * @param tc context 
  */
 static void
-acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+#if MINGW 
+static void
+accept_and_forward (struct ServiceListeningInfo *serviceListeningInfo)
 {
-  struct ServiceListeningInfo *serviceListeningInfo = cls;
   struct ForwardedConnection *fc;
 
-  serviceListeningInfo->acceptTask = GNUNET_SCHEDULER_NO_TASK;
-  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
-    return;
   fc = GNUNET_malloc (sizeof (struct ForwardedConnection));
   fc->listen_info = serviceListeningInfo;
   fc->service_to_client_bufferPos = fc->service_to_client_buffer;
@@ -879,6 +879,9 @@
                  serviceListeningInfo->serviceName,
                  STRERROR (errno));
       GNUNET_free (fc);
+      GNUNET_CONTAINER_DLL_insert (serviceListeningInfoList_head,
+                                  serviceListeningInfoList_tail, 
+                                  serviceListeningInfo); 
       serviceListeningInfo->acceptTask =
        GNUNET_SCHEDULER_add_read_net (scheduler,
                                       GNUNET_TIME_UNIT_FOREVER_REL, 
@@ -889,10 +892,7 @@
     }
   GNUNET_break (GNUNET_OK ==
                GNUNET_NETWORK_socket_close 
(serviceListeningInfo->listeningSocket));
-  GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
-                              serviceListeningInfoList_tail, 
-                              serviceListeningInfo);
-  start_service (NULL, serviceListeningInfo->serviceName);
+  start_service (NULL, serviceListeningInfo->serviceName, NULL);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO, 
              _("Service `%s' started\n"),
              fc->listen_info->serviceName);
@@ -909,9 +909,75 @@
                                &start_forwarding,
                                fc);
 }
+#endif
 
 
 /**
+ * First connection has come to the listening socket associated with the 
service,
+ * create the service in order to relay the incoming connection to it
+ * 
+ * @param cls callback data, struct ServiceListeningInfo describing a listen 
socket
+ * @param tc context 
+ */
+static void
+acceptConnection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct ServiceListeningInfo *sli = cls;
+  struct ServiceListeningInfo *pos;
+  struct ServiceListeningInfo *next;
+  int *lsocks;
+  unsigned int ls;
+
+  sli->acceptTask = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
+    return;
+  GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
+                              serviceListeningInfoList_tail, 
+                              sli);  
+#ifndef MINGW
+  lsocks = NULL;
+  ls = 0;
+  next = serviceListeningInfoList_head;
+  while (NULL != (pos = next))
+    {
+      next = pos->next;
+      if (0 == strcmp (pos->serviceName,
+                      sli->serviceName))
+       {
+         GNUNET_array_append (lsocks, ls, 
+                              GNUNET_NETWORK_get_fd (pos->listeningSocket));   
  
+         GNUNET_free (pos->listeningSocket); /* deliberately no closing! */
+         GNUNET_free (pos->service_addr);
+         GNUNET_free (pos->serviceName);
+         GNUNET_SCHEDULER_cancel (scheduler,
+                                  pos->acceptTask);
+         GNUNET_CONTAINER_DLL_remove (serviceListeningInfoList_head,
+                                      serviceListeningInfoList_tail, 
+                                      pos);
+         GNUNET_free (pos);
+       }
+    }
+  GNUNET_array_append (lsocks, ls, 
+                      GNUNET_NETWORK_get_fd (sli->listeningSocket));
+  GNUNET_free (sli->listeningSocket); /* deliberately no closing! */
+  GNUNET_free (sli->service_addr);
+  GNUNET_array_append (lsocks, ls, -1);
+  start_service (NULL, 
+                sli->serviceName,
+                lsocks);
+  ls = 0;
+  while (lsocks[ls] != -1)
+    GNUNET_break (0 == close (lsocks[ls++]));      
+  GNUNET_array_grow (lsocks, ls, 0);
+  GNUNET_free (sli->serviceName);
+  GNUNET_free (sli); 
+#else
+  accept_and_forward (sli);  
+#endif
+}
+
+
+/**
  * Creating a listening socket for each of the service's addresses and
  * wait for the first incoming connection to it
  * 

Modified: gnunet/src/include/gnunet_network_lib.h
===================================================================
--- gnunet/src/include/gnunet_network_lib.h     2010-06-23 14:23:25 UTC (rev 
11906)
+++ gnunet/src/include/gnunet_network_lib.h     2010-06-23 14:23:50 UTC (rev 
11907)
@@ -199,6 +199,7 @@
 ssize_t GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle *desc,
                                     const void *buffer, size_t length);
 
+
 /**
  * Send data to a particular destination (always non-blocking).
  * This function only works for UDP sockets.

Modified: gnunet/src/include/gnunet_os_lib.h
===================================================================
--- gnunet/src/include/gnunet_os_lib.h  2010-06-23 14:23:25 UTC (rev 11906)
+++ gnunet/src/include/gnunet_os_lib.h  2010-06-23 14:23:50 UTC (rev 11907)
@@ -216,12 +216,15 @@
 /**
  * Start a process.
  *
+ * @param lsocks array of listen sockets to dup systemd-style (or NULL);
+ *         must be NULL on platforms where dup is not supported
  * @param filename name of the binary
  * @param argv NULL-terminated list of arguments to the process,
  *             including the process name as the first argument
  * @return process ID of the new process, -1 on error
  */
-pid_t GNUNET_OS_start_process_v (const char *filename, char *const argv[]);
+pid_t GNUNET_OS_start_process_v (const int *lsocks,
+                                const char *filename, char *const argv[]);
 
 
 /**

Modified: gnunet/src/util/os_priority.c
===================================================================
--- gnunet/src/util/os_priority.c       2010-06-23 14:23:25 UTC (rev 11906)
+++ gnunet/src/util/os_priority.c       2010-06-23 14:23:50 UTC (rev 11907)
@@ -329,16 +329,43 @@
 /**
  * Start a process.
  *
+ * @param lsocks array of listen sockets to dup systemd-style (or NULL);
+ *         must be NULL on platforms where dup is not supported
  * @param filename name of the binary
  * @param argv NULL-terminated list of arguments to the process
  * @return process ID of the new process, -1 on error
  */
 pid_t
-GNUNET_OS_start_process_v (const char *filename, char *const argv[])
+GNUNET_OS_start_process_v (const int *lsocks,
+                          const char *filename, char *const argv[])
 {
 #ifndef MINGW
   pid_t ret;
+  char lpid[16];
+  char fds[16];
+  int i;
+  int j;
+  int k;
+  int tgt;
+  int flags;
+  int *lscp;
+  unsigned int ls;    
 
+  lscp = NULL;
+  ls = 0;
+  if (lsocks != NULL)
+    {
+      i = 0;
+      while (-1 != (k = lsocks[i++]))
+       {
+         flags = fcntl (k, F_GETFD);
+         GNUNET_assert (flags >= 0);
+         flags &= ~FD_CLOEXEC;
+         (void) fcntl (k, F_SETFD, flags);
+         GNUNET_array_append (lscp, ls, k);
+       }
+      GNUNET_array_append (lscp, ls, -1);
+    }
 #if HAVE_WORKING_VFORK
   ret = vfork ();
 #else
@@ -366,6 +393,48 @@
         }
       return ret;
     }
+  if (lscp != NULL)
+    {
+      /* read systemd documentation... */
+      GNUNET_snprintf (lpid, sizeof (lpid), "%u", getpid());
+      setenv ("LISTEN_PID", lpid, 1);      
+      i = 0;
+      tgt = 3;
+      while (-1 != lscp[i])
+       {
+         j = i + 1;
+         while (-1 != lscp[j])
+           {
+             if (lscp[j] == tgt)
+               {
+                 /* dup away */
+                 k = dup (lscp[j]);
+                 GNUNET_assert (-1 != k);
+                 GNUNET_assert (0 == close (lscp[j]));
+                 lscp[j] = k;
+                 break;
+               }
+             j++;
+           }
+         if (lscp[i] != tgt)
+           {
+             /* Bury any existing FD, no matter what; they should all be closed
+                on exec anyway and the important onces have been dup'ed away */
+             (void) close (tgt);             
+             GNUNET_assert (-1 != dup2 (lscp[i], tgt));
+           }
+         /* set close-on-exec flag */
+         flags = fcntl (tgt, F_GETFD);
+         GNUNET_assert (flags >= 0);
+         flags &= ~FD_CLOEXEC;
+         (void) fcntl (tgt, F_SETFD, flags);
+         tgt++;
+         i++;
+       }
+      GNUNET_snprintf (fds, sizeof (fds), "%u", i);
+      setenv ("LISTEN_FDS", fds, 1); 
+    }
+  GNUNET_array_grow (lscp, ls, 0);
   execvp (filename, argv);
   GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "execvp", filename);
   _exit (1);
@@ -379,6 +448,7 @@
   char *non_const_filename = NULL;
   int filenamelen = 0;
 
+  GNUNET_assert (lsocks == NULL);
   /* Count the number of arguments */
   arg = argv;
   while (*arg)




reply via email to

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