- assert hard
[oweals/gnunet.git] / src / arm / gnunet-service-arm.c
index 064cb9777c0af57edd2dddd4fd05e8dc60674236..f16fd5265c9392b4bb38313c69517069fb5c8e1f 100644 (file)
 #include "gnunet_protocols.h"
 #include "arm.h"
 
-/**
- * Threshold after which exponential backoff shouldn't increase (in ms); 30m
- */
-#define EXPONENTIAL_BACKOFF_THRESHOLD GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
-
-
 /**
  * List of our services.
  */
@@ -145,6 +139,12 @@ struct ServiceList
    */
   struct GNUNET_TIME_Absolute restart_at;
 
+  /**
+   * Time we asked the service to shut down (used to calculate time it took
+   * the service to terminate).
+   */
+  struct GNUNET_TIME_Absolute killed_at;
+
   /**
    * Is this service to be started by default (or did a client tell us explicitly
    * to start it)?  GNUNET_NO if the service is started only upon 'accept' on a
@@ -152,6 +152,11 @@ struct ServiceList
    */
   int is_default;
 
+  /**
+   * Should we use pipes to signal this process? (YES for Java binaries and if we
+   * are on Windoze).
+   */
+  int pipe_control;
 };
 
 /**
@@ -235,6 +240,7 @@ start_process (struct ServiceList *sl)
   struct ServiceListeningInfo *sli;
   SOCKTYPE *lsocks;
   unsigned int ls;
+  char *binary;
 
   /* calculate listen socket list */
   lsocks = NULL;
@@ -303,20 +309,38 @@ start_process (struct ServiceList *sl)
   use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG");
 
   /* actually start process */
-#if DEBUG_ARM
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Starting service `%s' using binary `%s' and configuration `%s'\n",
              sl->name, sl->binary, sl->config);
-#endif
+  binary = GNUNET_OS_get_libexec_binary_path (sl->binary);
   GNUNET_assert (NULL == sl->proc);
   if (GNUNET_YES == use_debug)
-    sl->proc =
-      do_start_process (lsocks, loprefix, sl->binary, "-c", sl->config, "-L",
-                       "DEBUG", options, NULL);
+  {
+    if (NULL == sl->config)
+      sl->proc =
+       do_start_process (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                         lsocks, loprefix, binary, "-L",
+                         "DEBUG", options, NULL);
+    else
+      sl->proc =
+       do_start_process (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                         lsocks, loprefix, binary, "-c", sl->config, "-L",
+                         "DEBUG", options, NULL);
+  }
   else
-    sl->proc =
-      do_start_process (lsocks, loprefix, sl->binary, "-c", sl->config,
-                       options, NULL);
+  {
+    if (NULL == sl->config)
+      sl->proc =
+       do_start_process (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                         lsocks, loprefix, binary, 
+                         options, NULL);
+    else
+      sl->proc =
+       do_start_process (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                         lsocks, loprefix, binary, "-c", sl->config,
+                         options, NULL);
+  }
+  GNUNET_free (binary);
   if (sl->proc == NULL)
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"),
                sl->name);
@@ -350,10 +374,8 @@ write_result (void *cls, size_t size, void *buf)
                _("Could not send status result to client\n"));
     return 0;                  /* error, not much we can do */
   }
-#if DEBUG_ARM
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending status response %u to client\n", (unsigned int) *res);
-#endif
   GNUNET_assert (size >= sizeof (struct GNUNET_ARM_ResultMessage));
   msg = buf;
   msg->header.size = htons (sizeof (struct GNUNET_ARM_ResultMessage));
@@ -363,6 +385,43 @@ write_result (void *cls, size_t size, void *buf)
   return sizeof (struct GNUNET_ARM_ResultMessage);
 }
 
+/**
+ * Transmit the list of running services.
+ * 
+ * @param cls pointer to struct GNUNET_ARM_ListResultMessage with the message
+ * @param size number of bytes available in buf
+ * @param buf where to copy the message, NULL on error
+ * @return number of bytes copied to buf
+ */
+static size_t
+write_list_result (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_ARM_ListResultMessage *msg = cls;
+  struct GNUNET_ARM_ListResultMessage *rslt;
+  size_t rslt_size;
+  
+  if (buf == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Could not send list result to client\n"));
+    return 0;                   /* error, not much we can do */
+  }
+  
+  GNUNET_assert (size >= msg->header.size);
+  rslt = buf;
+  rslt->header.size = htons (msg->header.size);
+  rslt->header.type = htons (msg->header.type);
+  rslt->count = htons (msg->count);
+  
+  size_t list_size = msg->header.size 
+                     - sizeof (struct GNUNET_ARM_ListResultMessage);  
+  memcpy (&rslt[1], &msg[1], list_size);
+
+  rslt_size = msg->header.size;
+  GNUNET_free (msg);
+  return rslt_size;
+}
+
 
 /**
  * Signal our client that we will start or stop the
@@ -430,6 +489,7 @@ accept_connection (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct ServiceList *sl = sli->sl;
 
   sli->accept_task = GNUNET_SCHEDULER_NO_TASK;
+  GNUNET_assert (GNUNET_NO == in_shutdown);
   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
     return;
   start_process (sl);
@@ -448,7 +508,7 @@ static void
 create_listen_socket (struct sockaddr *sa, socklen_t addr_len,
                      struct ServiceList *sl)
 {
-  const static int on = 1;
+  static int on = 1;
   struct GNUNET_NETWORK_Handle *sock;
   struct ServiceListeningInfo *sli;
 
@@ -559,7 +619,7 @@ handle_start (void *cls, struct GNUNET_SERVER_Client *client,
   const char *servicename;
   struct ServiceList *sl;
   uint16_t size;
-
+  
   size = ntohs (message->size);
   size -= sizeof (struct GNUNET_MessageHeader);
   servicename = (const char *) &message[1];
@@ -645,17 +705,73 @@ handle_stop (void *cls, struct GNUNET_SERVER_Client *client,
       signal_result (client, servicename, GNUNET_ARM_PROCESS_ALREADY_DOWN);
       return;
     }
-#if DEBUG_ARM
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Sending kill signal to service `%s', waiting for process to die.\n",
              servicename);
-#endif
+  sl->killed_at = GNUNET_TIME_absolute_get ();
   if (0 != GNUNET_OS_process_kill (sl->proc, SIGTERM))
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
   sl->killing_client = client;
   GNUNET_SERVER_client_keep (client);
 }
 
+/**
+ * Handle LIST-message.
+ *
+ * @param cls closure (always NULL)
+ * @param client identification of the client
+ * @param message the actual message
+ */
+static void
+handle_list (void *cls, struct GNUNET_SERVER_Client *client,
+             const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_ARM_ListResultMessage *msg;
+  size_t string_list_size;
+  size_t total_size;
+  struct ServiceList *sl;
+  uint16_t count;
+  
+  if (NULL == client)
+    return;
+  
+  count = 0;
+  string_list_size = 0;
+  /* first count the running processes get their name's size */
+  for (sl = running_head; sl != NULL; sl = sl->next)
+  {
+    if (sl->proc != NULL)
+    {
+      string_list_size += strlen (sl->name);
+      string_list_size += strlen (sl->binary);
+      string_list_size += 4;
+      count++;
+    }
+  }
+  total_size = sizeof (struct GNUNET_ARM_ListResultMessage) 
+               + string_list_size;
+  msg = GNUNET_malloc (total_size);
+  msg->header.size = total_size;
+  msg->header.type = GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT;
+  msg->count = count;
+  
+  char *pos = (char *)&msg[1];
+  for (sl = running_head; sl != NULL; sl = sl->next) 
+  {
+    if (sl->proc != NULL)
+    {
+      size_t s = strlen (sl->name) + strlen (sl->binary) + 4;
+      GNUNET_snprintf(pos, s, "%s (%s)", sl->name, sl->binary);
+      pos += s;
+    }
+  }
+  
+  GNUNET_SERVER_notify_transmit_ready (client,
+                                       msg->header.size,
+                                       GNUNET_TIME_UNIT_FOREVER_REL,
+                                       &write_list_result, msg);
+  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+}
 
 /**
  * We are done with everything.  Stop remaining
@@ -691,46 +807,47 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct ServiceListeningInfo *sli;
 
   if (GNUNET_SCHEDULER_NO_TASK != child_restart_task)
-    {
-      GNUNET_SCHEDULER_cancel (child_restart_task);
-      child_restart_task = GNUNET_SCHEDULER_NO_TASK;
-    }
+  {
+    GNUNET_SCHEDULER_cancel (child_restart_task);
+    child_restart_task = GNUNET_SCHEDULER_NO_TASK;
+  }
   in_shutdown = GNUNET_YES;
   /* first, stop listening */
   for (pos = running_head; NULL != pos; pos = pos->next)
-    {
-      while (NULL != (sli = pos->listen_head))
-       {
-         GNUNET_CONTAINER_DLL_remove (pos->listen_head,
-                                      pos->listen_tail, sli);
-         if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK)
-           {
-             GNUNET_SCHEDULER_cancel (sli->accept_task);
-             sli->accept_task = GNUNET_SCHEDULER_NO_TASK;
-           }
-         GNUNET_break (GNUNET_OK ==
-                       GNUNET_NETWORK_socket_close (sli->listen_socket));
-         GNUNET_free (sli->service_addr);
-         GNUNET_free (sli);
-       }
-    }
+  {
+    while (NULL != (sli = pos->listen_head))
+      {
+       GNUNET_CONTAINER_DLL_remove (pos->listen_head,
+                                    pos->listen_tail, sli);
+       if (sli->accept_task != GNUNET_SCHEDULER_NO_TASK)
+         {
+           GNUNET_SCHEDULER_cancel (sli->accept_task);
+           sli->accept_task = GNUNET_SCHEDULER_NO_TASK;
+         }
+       GNUNET_break (GNUNET_OK ==
+                     GNUNET_NETWORK_socket_close (sli->listen_socket));
+       GNUNET_free (sli->service_addr);
+       GNUNET_free (sli);
+      }
+  }
   /* then, shutdown all existing service processes */
   nxt = running_head;
   while (NULL != (pos = nxt))
+  {
+    nxt = pos->next;
+    if (pos->proc != NULL)
     {
-      nxt = pos->next;
-      if (pos->proc != NULL)
-       {
-         GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n",
-                     pos->name);
-         if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM))
-           GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
-       }
-      else
-       {
-         free_service (pos);
-       }
+      GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n",
+                 pos->name);
+      pos->killed_at = GNUNET_TIME_absolute_get ();
+      if (0 != GNUNET_OS_process_kill (pos->proc, SIGTERM))
+       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
     }
+    else
+    {
+      free_service (pos);
+    }
+  }
   /* finally, should all service processes be already gone, terminate for real */
   if (running_head == NULL)
     do_shutdown ();
@@ -760,56 +877,54 @@ delayed_restart_task (void *cls,
   /* check for services that need to be restarted due to
    * configuration changes or because the last restart failed */
   for (sl = running_head; NULL != sl; sl = sl->next)
+  {
+    if (NULL != sl->proc)
+      continue;
+    /* service is currently not running */
+    if (GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value ==
+       0)
     {
-      if (sl->proc == NULL)
-       {
-         /* service is currently not running */
-         if (GNUNET_TIME_absolute_get_remaining (sl->restart_at).rel_value ==
-             0)
-           {
-             /* restart is now allowed */
-             if (sl->is_default)
-               {
-                 /* process should run by default, start immediately */
-                 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                             _("Restarting service `%s'.\n"), sl->name);
-                 start_process (sl);
-               }
-             else
-               {
-                 /* process is run on-demand, ensure it is re-started if there is demand */
-                 for (sli = sl->listen_head; NULL != sli; sli = sli->next)
-                   if (GNUNET_SCHEDULER_NO_TASK == sli->accept_task)
-                     {
-                       /* accept was actually paused, so start it again */
-                       sli->accept_task =
-                         GNUNET_SCHEDULER_add_read_net
-                         (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket,
-                          &accept_connection, sli);
-                     }
-               }
-           }
-         else
-           {
-             /* update calculation for earliest time to reactivate a service */
-             lowestRestartDelay =
-               GNUNET_TIME_relative_min (lowestRestartDelay,
-                                         GNUNET_TIME_absolute_get_remaining
-                                         (sl->restart_at));
-           }
-       }
+      /* restart is now allowed */
+      if (sl->is_default)
+      {
+       /* process should run by default, start immediately */
+       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                   _("Restarting service `%s'.\n"), sl->name);
+       start_process (sl);
+      }
+      else
+      {
+       /* process is run on-demand, ensure it is re-started if there is demand */
+       for (sli = sl->listen_head; NULL != sli; sli = sli->next)
+         if (GNUNET_SCHEDULER_NO_TASK == sli->accept_task)
+         {
+           /* accept was actually paused, so start it again */
+           sli->accept_task =
+             GNUNET_SCHEDULER_add_read_net
+             (GNUNET_TIME_UNIT_FOREVER_REL, sli->listen_socket,
+              &accept_connection, sli);
+         }
+      }
     }
-  if (lowestRestartDelay.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+    else
     {
-#if DEBUG_ARM
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %llums\n",
-                 (unsigned long long) lowestRestartDelay.rel_value);
-#endif
-      child_restart_task =
-       GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
-                                                   GNUNET_SCHEDULER_PRIORITY_IDLE, 
-                                                   &delayed_restart_task, NULL);
+      /* update calculation for earliest time to reactivate a service */
+      lowestRestartDelay =
+       GNUNET_TIME_relative_min (lowestRestartDelay,
+                                 GNUNET_TIME_absolute_get_remaining
+                                 (sl->restart_at));
     }
+  }
+  if (lowestRestartDelay.rel_value != GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 
+               "Will restart process in %s\n",
+               GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay, GNUNET_YES));
+    child_restart_task =
+      GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
+                                                 GNUNET_SCHEDULER_PRIORITY_IDLE, 
+                                                 &delayed_restart_task, NULL);
+  }
 }
 
 
@@ -854,11 +969,11 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       next = pos->next;
 
       if (pos->proc == NULL)
-       {
-         if (GNUNET_YES == in_shutdown)
-           free_service (pos);
-         continue;
-       }
+      {
+       if (GNUNET_YES == in_shutdown)
+         free_service (pos);
+       continue;
+      }
       if ((GNUNET_SYSERR ==
           (ret =
            GNUNET_OS_process_status (pos->proc, &statusType, &statusCode)))
@@ -866,21 +981,28 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
              || (statusType == GNUNET_OS_PROCESS_RUNNING)))
        continue;
       if (statusType == GNUNET_OS_PROCESS_EXITED)
-       {
-         statstr = _( /* process termination method */ "exit");
-         statcode = statusCode;
-       }
+      {
+       statstr = _( /* process termination method */ "exit");
+       statcode = statusCode;
+      }
       else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
-       {
-         statstr = _( /* process termination method */ "signal");
-         statcode = statusCode;
-       }
+      {
+       statstr = _( /* process termination method */ "signal");
+       statcode = statusCode;
+      }
       else
-       {
-         statstr = _( /* process termination method */ "unknown");
-         statcode = 0;
-       }
-      GNUNET_OS_process_close (pos->proc);
+      {
+       statstr = _( /* process termination method */ "unknown");
+       statcode = 0;
+      }
+      if (0 != pos->killed_at.abs_value)
+      {
+       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                   _("Service `%s' took %s to terminate\n"),
+                   pos->name,
+                   GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (pos->killed_at), GNUNET_YES));
+      }
+      GNUNET_OS_process_destroy (pos->proc);
       pos->proc = NULL;
       if (NULL != pos->killing_client)
        {
@@ -915,10 +1037,7 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                            pos->name, statstr, statcode, pos->backoff.rel_value);
              /* schedule restart */
              pos->restart_at = GNUNET_TIME_relative_to_absolute (pos->backoff);
-             pos->backoff =
-               GNUNET_TIME_relative_min (EXPONENTIAL_BACKOFF_THRESHOLD,
-                                         GNUNET_TIME_relative_multiply
-                                         (pos->backoff, 2));
+             pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
             }
          if (GNUNET_SCHEDULER_NO_TASK != child_restart_task)
            GNUNET_SCHEDULER_cancel (child_restart_task);
@@ -940,41 +1059,6 @@ maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 }
 
 
-/**
- * Transmit our shutdown acknowledgement to the client.
- *
- * @param cls the 'struct GNUNET_SERVER_Client'
- * @param size number of bytes available in buf
- * @param buf where to write the message
- * @return number of bytes written
- */
-static size_t
-transmit_shutdown_ack (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_SERVER_Client *client = cls;
-  struct GNUNET_ARM_ResultMessage *msg;
-
-  if (size < sizeof (struct GNUNET_ARM_ResultMessage))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                 _("Failed to transmit shutdown ACK.\n"));
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return 0;                        /* client disconnected */
-    }
-  /* Make the connection flushing for the purpose of ACK transmitting,
-   * needed on W32 to ensure that the message is even received, harmless
-   * on other platforms... */
-  GNUNET_break (GNUNET_OK == GNUNET_SERVER_client_disable_corking (client));
-  msg = (struct GNUNET_ARM_ResultMessage *) buf;
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_RESULT);
-  msg->header.size = htons (sizeof (struct GNUNET_ARM_ResultMessage));
-  msg->status = htonl ((uint32_t) GNUNET_ARM_PROCESS_SHUTDOWN);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  GNUNET_SERVER_client_drop (client);
-  return sizeof (struct GNUNET_ARM_ResultMessage);
-}
-
-
 /**
  * Handler for SHUTDOWN message.
  *
@@ -987,11 +1071,6 @@ handle_shutdown (void *cls, struct GNUNET_SERVER_Client *client,
                 const struct GNUNET_MessageHeader *message)
 {
   GNUNET_SCHEDULER_shutdown ();
-  GNUNET_SERVER_client_keep (client);
-  GNUNET_SERVER_notify_transmit_ready (client,
-                                      sizeof (struct GNUNET_ARM_ResultMessage),
-                                      GNUNET_TIME_UNIT_FOREVER_REL,
-                                      &transmit_shutdown_ack, client);
   GNUNET_SERVER_client_persist_ (client);
 }
 
@@ -1050,26 +1129,35 @@ setup_service (void *cls, const char *section)
     return;
   }
   config = NULL;
-  if ((GNUNET_OK !=
-       GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG",
-                                               &config)) ||
+  if (( (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (cfg, section, "CONFIG",
+                                                 &config)) &&
+       (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_filename (cfg, "PATHS", "DEFAULTCONFIG",
+                                                 &config)) ) ||
       (0 != STAT (config, &sbuf)))
+  {
+    if (NULL != config)
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                 _
-                 ("Configuration file `%s' for service `%s' not valid: %s\n"),
-                 config, section,
-                 (config == NULL) ? _("option missing") : STRERROR (errno));
-      GNUNET_free (binary);
-      GNUNET_free_non_null (config);
-      return;
+      GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING, 
+                                section, "CONFIG",
+                                STRERROR (errno));
+      GNUNET_free (config);
+      config = NULL;
     }
+  }
   sl = GNUNET_malloc (sizeof (struct ServiceList));
   sl->name = GNUNET_strdup (section);
   sl->binary = binary;
   sl->config = config;
   sl->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
   sl->restart_at = GNUNET_TIME_UNIT_FOREVER_ABS;
+#if WINDOWS
+  sl->pipe_control = GNUNET_YES;
+#else
+  if (GNUNET_CONFIGURATION_have_value (cfg, section, "PIPECONTROL"))
+    sl->pipe_control = GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "PIPECONTROL");
+#endif  
   GNUNET_CONTAINER_DLL_insert (running_head, running_tail, sl);
   if (GNUNET_YES !=
       GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "AUTOSTART"))
@@ -1101,6 +1189,8 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
     {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0},
     {&handle_shutdown, NULL, GNUNET_MESSAGE_TYPE_ARM_SHUTDOWN,
      sizeof (struct GNUNET_MessageHeader)},
+    {&handle_list, NULL, GNUNET_MESSAGE_TYPE_ARM_LIST, 
+     sizeof (struct GNUNET_MessageHeader)},
     {NULL, NULL, 0, 0}
   };
   char *defaultservices;
@@ -1110,7 +1200,6 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv,
   cfg = c;
   server = serv;
   GNUNET_assert (serv != NULL);
-  GNUNET_SERVER_ignore_shutdown (serv, GNUNET_YES);
   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
                                NULL);
   child_death_task =
@@ -1188,7 +1277,8 @@ main (int argc, char *const *argv)
     GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death);
   ret =
     (GNUNET_OK ==
-     GNUNET_SERVICE_run (argc, argv, "arm", GNUNET_YES, &run, NULL)) ? 0 : 1;
+     GNUNET_SERVICE_run (argc, argv, "arm", 
+                        GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, &run, NULL)) ? 0 : 1;
   GNUNET_SIGNAL_handler_uninstall (shc_chld);
   shc_chld = NULL;
   GNUNET_DISK_pipe_close (sigpipe);