*/
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
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
const char *servicename;
struct ServiceList *sl;
uint16_t size;
-
+
size = ntohs (message->size);
size -= sizeof (struct GNUNET_MessageHeader);
servicename = (const char *) &message[1];
"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
{
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");
}
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;
- }
+ {
+ 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_close (pos->proc);
pos->proc = NULL;
if (NULL != pos->killing_client)
GNUNET_SERVER_client_persist_ (client);
}
-
/**
* Signal handler called for SIGCHLD. Triggers the
* respective handler by writing to the trigger pipe.
{&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;