GNUNET_free (h);
}
+struct ARM_ShutdownContext
+{
+ /**
+ * Callback to call once shutdown complete.
+ */
+ GNUNET_ARM_Callback cb;
+
+ /**
+ * Closure for callback.
+ */
+ void *cb_cls;
+};
+
+
/**
* Internal state for a request with ARM.
change_service (h, service_name, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_START);
}
+/**
+ * Callback from the arm stop service call, indicates that the arm service
+ * is well and truly dead.
+ *
+ * @param cls closure for the callback
+ * @param tc scheduler context
+ */
+void arm_shutdown_callback (void *cls,
+ int reason)
+{
+ struct ARM_ShutdownContext *arm_shutdown_ctx = cls;
+
+ if (arm_shutdown_ctx->cb != NULL)
+ arm_shutdown_ctx->cb (arm_shutdown_ctx->cb_cls, reason);
+}
+
/**
* Stop a service.
struct GNUNET_TIME_Relative timeout,
GNUNET_ARM_Callback cb, void *cb_cls)
{
+ struct ARM_ShutdownContext *arm_shutdown_ctx;
+
+ arm_shutdown_ctx = GNUNET_malloc(sizeof(struct ARM_ShutdownContext));
+ arm_shutdown_ctx->cb = cb;
+ arm_shutdown_ctx->cb_cls = cb_cls;
+
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
_("Stopping service `%s' within %llu ms\n"), service_name,
(unsigned long long) timeout.value);
if (0 == strcasecmp ("arm", service_name))
{
- GNUNET_CLIENT_service_shutdown (h->client);
+ GNUNET_CLIENT_service_shutdown (h->sched, h->client, timeout, &arm_shutdown_callback, arm_shutdown_ctx);
h->client = NULL;
- if (cb != NULL)
- cb (cb_cls, GNUNET_NO);
return;
}
change_service (h, service_name, timeout, cb, cb_cls, GNUNET_MESSAGE_TYPE_ARM_STOP);
#include "gnunet_time_lib.h"
/**
- * Timeout for all operations.
+ * Timeout for stopping services. Long to give some services a real chance.
*/
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 50)
+#define STOP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
+
+/**
+ * Timeout for starting services, very short because of the strange way start works
+ * (by checking if running before starting, so really this time is always waited on
+ * startup (annoying)).
+ */
+#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 50)
/**
* Set if we are to shutdown all services (including ARM).
*/
static int start;
+/**
+ * Set if we are to stop/start default services (including ARM).
+ */
+static int restart;
+
/**
* Set if we should delete configuration and temp directory on exit.
*/
case GNUNET_OK:
if (quiet != GNUNET_YES)
fprintf(stdout, _("Service `%s' is now running.\n"), service);
+ if ((phase - 1 != 2) && (phase - 1 != 3))
+ {
+ if (quiet != GNUNET_YES)
+ fprintf(stdout, _("Failed to stop service `%s'!\n"), service);
+ ret = 1;
+ }
break;
case GNUNET_NO:
if (quiet != GNUNET_YES)
fprintf(stdout, _("Service `%s' is not running.\n"), service);
+ if ((phase - 1 != 0) && (phase - 1 != 1))
+ {
+ if (quiet != GNUNET_YES)
+ fprintf(stdout, _("Failed to start service `%s'!\n"), service);
+ ret = 1;
+ }
break;
case GNUNET_SYSERR:
if (quiet != GNUNET_YES)
fprintf(stdout,
- _("Error updating service `%s': ARM not running\n"), service);
+ _("Some error communicating with service `%s'.\n"), service);
+ ret = 1;
break;
}
+
GNUNET_SCHEDULER_add_continuation (sched,
&cps_loop,
NULL,
case 0:
if (term != NULL)
{
- GNUNET_ARM_stop_service (h, term, TIMEOUT, &confirm_cb, term);
+ GNUNET_ARM_stop_service (h, term, STOP_TIMEOUT, &confirm_cb, term);
return;
}
break;
case 1:
- if (end)
+ if ((end) || (restart))
{
- GNUNET_ARM_stop_service (h, "arm", TIMEOUT, &confirm_cb, "arm");
+ GNUNET_ARM_stop_service (h, "arm", STOP_TIMEOUT, &confirm_cb, "arm");
return;
}
break;
case 2:
if (start)
{
- GNUNET_ARM_start_service (h, "arm", TIMEOUT, &confirm_cb, "arm");
+ GNUNET_ARM_start_service (h, "arm", START_TIMEOUT, &confirm_cb, "arm");
return;
}
break;
case 3:
if (init != NULL)
{
- GNUNET_ARM_start_service (h, init, TIMEOUT, &confirm_cb, init);
+ GNUNET_ARM_start_service (h, init, START_TIMEOUT, &confirm_cb, init);
return;
}
break;
case 4:
if (test != NULL)
{
- GNUNET_CLIENT_service_test (sched, test, cfg, TIMEOUT, &confirm_task, test);
+ GNUNET_CLIENT_service_test (sched, test, cfg, START_TIMEOUT, &confirm_task, test);
return;
}
break;
+ case 5:
+ if (restart) /* FIXME:
+ * Restart should be a legal option but this is a hack.
+ * The proper thing to do would be have gnunet-service-arm
+ * signal us when actually shut down, and then initiate
+ * the startup. Instead we just sleep for two seconds
+ * and hope that's enough time for shutdown to have happened.
+ */
+ {
+ GNUNET_ARM_disconnect (h);
+ phase = 0;
+ end = 0;
+ start = 1;
+ restart = 0;
+ h = GNUNET_ARM_connect (cfg, sched, NULL);
+ if (h == NULL)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ _("Fatal error initializing ARM API.\n"));
+ ret = 1;
+ return;
+ }
+ GNUNET_SCHEDULER_add_now(sched, &cps_loop, NULL);
+ return;
+ }
default: /* last phase */
GNUNET_ARM_disconnect (h);
if ((end == GNUNET_YES) && (delete == GNUNET_YES))
GNUNET_YES, &GNUNET_GETOPT_set_string, &term},
{'s', "start", NULL, gettext_noop ("start all GNUnet default services"),
GNUNET_NO, &GNUNET_GETOPT_set_one, &start},
+ {'r', "restart", NULL, gettext_noop ("stop and start all GNUnet default services"),
+ GNUNET_NO, &GNUNET_GETOPT_set_one, &restart},
{'t', "test", "SERVICE",
gettext_noop ("test if a particular service is running"),
GNUNET_YES, &GNUNET_GETOPT_set_string, &test},
*/
#define EXPONENTIAL_BACKOFF_THRESHOLD (1000 * 60 * 30)
+#define DELAY_SHUTDOWN GNUNET_NO
/**
* List of our services.
child_death_task = GNUNET_SCHEDULER_NO_TASK;
}
+#if DELAY_SHUTDOWN
+/**
+ * Dummy task to delay arm shutdown.
+ */
+void dummy_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext * tc)
+{
+ GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Dummy task executing\n");
+ return;
+}
+#endif
/**
* Task run for shutdown.
shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct ServiceList *pos;
-
#if DEBUG_ARM
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Stopping all services\n"));
#endif
}
pos = pos->next;
}
+#if DELAY_SHUTDOWN
+ GNUNET_SCHEDULER_add_delayed(sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 2), &dummy_task, NULL);
+#endif
if (running == NULL)
do_shutdown ();
}
sighandler_child_death ()
{
static char c;
-
GNUNET_break (1 ==
GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle
(sigpipe, GNUNET_DISK_PIPE_END_WRITE), &c,
#define START_ARM GNUNET_YES
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
+#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 50)
+
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
static struct GNUNET_SCHEDULER_Handle *sched;
static int ok = 1;
+static void
+arm_stopped (void *cls, int success)
+{
+ if (success != GNUNET_NO)
+ ok = 1;
+ else
+ ok = 0;
+}
static void
arm_notify_stop (void *cls, int success)
{
GNUNET_assert (success == GNUNET_NO);
#if START_ARM
- GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, NULL, NULL);
+ GNUNET_ARM_stop_service (arm, "arm", TIMEOUT, &arm_stopped, NULL);
#endif
}
arm_notify (void *cls, int success)
{
GNUNET_assert (success == GNUNET_YES);
- GNUNET_ARM_start_service (arm, "resolver", TIMEOUT, &resolver_notify, NULL);
+ GNUNET_ARM_start_service (arm, "resolver", START_TIMEOUT, &resolver_notify, NULL);
}
sched = s;
arm = GNUNET_ARM_connect (cfg, sched, NULL);
#if START_ARM
- GNUNET_ARM_start_service (arm, "arm", TIMEOUT, &arm_notify, NULL);
+ GNUNET_ARM_start_service (arm, "arm", START_TIMEOUT, &arm_notify, NULL);
#else
arm_notify (NULL, GNUNET_YES);
#endif
static struct GNUNET_ARM_Handle *arm;
static int ok = 1;
+static int trialCount;
+static struct GNUNET_TIME_Absolute startedWaitingAt;
+struct GNUNET_TIME_Relative waitedFor;
+
#if LOG_BACKOFF
static FILE *killLogFilePtr;
static char *killLogFileName;
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
static char a;
- static int trialCount = 0;
trialCount++;
}
+static void
+shutdown_cont (void *cls, int reason)
+{
+ trialCount++;
+ startedWaitingAt = GNUNET_TIME_absolute_get();
+ GNUNET_SCHEDULER_add_delayed (sched,
+ waitedFor,
+ &do_test,
+ NULL);
+}
static void
kill_task (void *cbData,
const struct GNUNET_SCHEDULER_TaskContext *tc)
{
static struct GNUNET_CLIENT_Connection * doNothingConnection = NULL;
- static struct GNUNET_TIME_Absolute startedWaitingAt;
- struct GNUNET_TIME_Relative waitedFor;
- static int trialCount = 0;
-
+
if (NULL != cbData) {
waitedFor = GNUNET_TIME_absolute_get_duration (startedWaitingAt);
+
#if LOG_BACKOFF
fprintf(killLogFilePtr,
"Waited for: %llu ms\n",
}
/* Use the created connection to kill the doNothingTask */
- GNUNET_CLIENT_service_shutdown(doNothingConnection);
- trialCount++;
- startedWaitingAt = GNUNET_TIME_absolute_get();
- GNUNET_SCHEDULER_add_delayed (sched,
- waitedFor,
- &do_test,
- NULL);
+ GNUNET_CLIENT_service_shutdown(sched, doNothingConnection, TIMEOUT, &shutdown_cont, NULL);
+
}