*/
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
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
GNUNET_assert (NULL == sl->proc);
if (GNUNET_YES == use_debug)
sl->proc =
- do_start_process (sl->pipe_control,
+ do_start_process (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
lsocks, loprefix, sl->binary, "-c", sl->config, "-L",
"DEBUG", options, NULL);
else
sl->proc =
- do_start_process (sl->pipe_control,
+ do_start_process (sl->pipe_control, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
lsocks, loprefix, sl->binary, "-c", sl->config,
options, NULL);
if (sl->proc == NULL)
_("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));
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;
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;
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 ();
/* 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 %llums\n",
+ (unsigned long long) lowestRestartDelay.rel_value);
+ child_restart_task =
+ GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
+ GNUNET_SCHEDULER_PRIORITY_IDLE,
+ &delayed_restart_task, NULL);
+ }
}
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)))
|| (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 %llu ms to terminate\n"),
+ pos->name,
+ GNUNET_TIME_absolute_get_duration (pos->killed_at).rel_value);
+ }
+ GNUNET_OS_process_destroy (pos->proc);
pos->proc = NULL;
if (NULL != pos->killing_client)
{
}
-/**
- * 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.
*
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);
}
+
/**
* Signal handler called for SIGCHLD. Triggers the
* respective handler by writing to the trigger pipe.
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 =
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);