/**
* Our configuration
*/
-static struct GNUNET_CONFIGURATION_Handle *cfg;
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
/**
* Our scheduler.
{
uint16_t *res;
+ if (NULL == client)
+ return;
#if DEBUG_ARM
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Telling client that service `%s' is now %s\n",
}
-/**
- * Find the process with the given PID in the
- * given list.
- *
- * @return NULL if it was not found
- */
-static struct ServiceList *
-find_pid (pid_t pid)
-{
- struct ServiceList *pos;
-
- pos = running;
- while (pos != NULL)
- {
- if (pos->pid == pid)
- return pos;
- pos = pos->next;
- }
- return NULL;
-}
-
-
/**
* Find the process with the given service
* name in the given list, remove it and return it.
start_process (struct ServiceList *sl)
{
char *loprefix;
+ char *options;
char **argv;
unsigned int argv_size;
char *lopos;
+ char *optpos;
const char *firstarg;
int use_debug;
GNUNET_CONFIGURATION_get_value_string (cfg,
sl->name, "PREFIX", &loprefix))
loprefix = GNUNET_strdup (prefix_command);
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ sl->name, "OPTIONS", &options))
+ options = GNUNET_strdup ("");
use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG");
GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), sl->name);
"Starting service `%s' using binary `%s' and configuration `%s'\n",
sl->name, sl->binary, sl->config);
#endif
- argv_size = 5;
+ argv_size = 6;
if (use_debug)
argv_size += 2;
lopos = loprefix;
argv_size++;
lopos++;
}
+ optpos = options;
+ while ('\0' != *optpos)
+ {
+ if (*optpos == ' ')
+ argv_size++;
+ optpos++;
+ }
firstarg = NULL;
argv = GNUNET_malloc (argv_size * sizeof (char *));
argv_size = 0;
lopos = loprefix;
+
while ('\0' != *lopos)
{
while (*lopos == ' ')
argv[argv_size++] = "-L";
argv[argv_size++] = "DEBUG";
}
+ optpos = options;
+ while ('\0' != *optpos)
+ {
+ while (*optpos == ' ')
+ optpos++;
+ if (*optpos == '\0')
+ continue;
+ argv[argv_size++] = optpos;
+ while (('\0' != *optpos) && (' ' != *optpos))
+ optpos++;
+ if ('\0' == *optpos)
+ continue;
+ *optpos = '\0';
+ optpos++;
+ }
argv[argv_size++] = NULL;
sl->pid = GNUNET_OS_start_process_v (firstarg, argv);
GNUNET_free (argv);
GNUNET_free (loprefix);
+ GNUNET_free (options);
}
* Start the specified service.
*/
static void
-start_service (struct GNUNET_SERVER_Handle *server,
- struct GNUNET_SERVER_Client *client, const char *servicename)
+start_service (struct GNUNET_SERVER_Client *client, const char *servicename)
{
struct ServiceList *sl;
char *binary;
config, servicename);
signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
GNUNET_free (binary);
+ GNUNET_free (config);
return;
}
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _("Preparing to start `%s'\n"), servicename);
sl = GNUNET_malloc (sizeof (struct ServiceList));
sl->name = GNUNET_strdup (servicename);
sl->next = running;
sl->mtime = sbuf.st_mtime;
running = sl;
start_process (sl);
- signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP);
+ if (NULL != client)
+ signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UP);
}
{
struct GNUNET_SERVER_Client *client = cls;
/* find_name will remove "pos" from the list! */
- GNUNET_assert (pos == find_name (pos->name));
GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Service `%s' stopped\n", pos->name);
signal_result (client, pos->name, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
* Stop the specified service.
*/
static void
-stop_service (struct GNUNET_SERVER_Handle *server,
- struct GNUNET_SERVER_Client *client, const char *servicename)
+stop_service (struct GNUNET_SERVER_Client *client, const char *servicename)
{
struct ServiceList *pos;
struct GNUNET_CLIENT_Connection *sc;
+ unsigned long long port;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Preparing to stop `%s'\n", servicename);
pos = find_name (servicename);
- if (pos->kill_continuation != NULL)
+ if ((pos != NULL) && (pos->kill_continuation != NULL))
{
/* killing already in progress */
signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
}
else
{
- sc = GNUNET_CLIENT_connect (sched, servicename, cfg);
- GNUNET_CLIENT_service_shutdown (sc);
- GNUNET_CLIENT_disconnect (sc);
- signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
+ if ( (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_number (cfg,
+ servicename,
+ "PORT",
+ &port)) &&
+ (NULL != (sc = GNUNET_CLIENT_connect (sched, servicename, cfg))) )
+ {
+ GNUNET_CLIENT_service_shutdown (sc);
+ GNUNET_CLIENT_disconnect (sc);
+ signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_DOWN);
+ }
+ else
+ {
+ signal_result (client, servicename, GNUNET_MESSAGE_TYPE_ARM_IS_UNKNOWN);
+ }
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
}
* Handle START-message.
*
* @param cls closure (always NULL)
- * @param server the server handling the message
* @param client identification of the client
* @param message the actual message
* @return GNUNET_OK to keep the connection open,
*/
static void
handle_start (void *cls,
- struct GNUNET_SERVER_Handle *server,
struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- start_service (server, client, servicename);
+ start_service (client, servicename);
GNUNET_SERVER_receive_done (client, GNUNET_OK);
}
* Handle STOP-message.
*
* @param cls closure (always NULL)
- * @param server the server handling the message
* @param client identification of the client
* @param message the actual message
* @return GNUNET_OK to keep the connection open,
*/
static void
handle_stop (void *cls,
- struct GNUNET_SERVER_Handle *server,
struct GNUNET_SERVER_Client *client,
const struct GNUNET_MessageHeader *message)
{
GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
return;
}
- stop_service (server, client, servicename);
+ stop_service (client, servicename);
}
maint (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
struct ServiceList *pos;
- pid_t pid;
- int status;
+ struct ServiceList *prev;
+ struct ServiceList *next;
const char *statstr;
int statcode;
struct stat sbuf;
+ int ret;
if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
{
running = pos->next;
if (0 != PLIBC_KILL (pos->pid, SIGTERM))
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
- if (pos->pid != waitpid (pos->pid, NULL, 0))
+ if (GNUNET_OK != GNUNET_OS_process_wait(pos->pid))
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
free_entry (pos);
}
GNUNET_SCHEDULER_add_delayed (tc->sched,
GNUNET_YES,
GNUNET_SCHEDULER_PRIORITY_IDLE,
- GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
- MAINT_FREQUENCY, &maint, cfg);
+ GNUNET_SCHEDULER_NO_TASK,
+ MAINT_FREQUENCY, &maint, NULL);
/* check for services that died (WAITPID) */
- while (0 < (pid = waitpid (0, &status, WNOHANG)))
+ prev = NULL;
+ next = running;
+ while (NULL != (pos = next))
{
- if (WIFSTOPPED (status) || WIFCONTINUED (status))
- continue;
- pos = find_pid (pid);
- if (pos == NULL)
- {
- /* we killed the service */
- continue;
- }
- if (WIFEXITED (status))
- {
- statstr = _( /* process termination method */ "exit");
- statcode = WEXITSTATUS (status);
- }
- else if (WTERMSIG (status))
- {
- statstr = _( /* process termination method */ "signal");
- statcode = WTERMSIG (status);
- }
+ enum GNUNET_OS_ProcessStatusType statusType;
+ unsigned long statusCode;
+
+ next = pos->next;
+ if (pos->pid == 0)
+ {
+ if (NULL != pos->kill_continuation)
+ {
+ if (prev == NULL)
+ running = next;
+ else
+ prev->next = next;
+ pos->kill_continuation (pos->kill_continuation_cls, pos);
+ }
+ continue;
+ }
+ if ( (GNUNET_SYSERR == (ret = GNUNET_OS_process_status(pos->pid,
+ &statusType,
+ &statusCode))) ||
+ ( (ret == GNUNET_NO) ||
+ (statusType == GNUNET_OS_PROCESS_STOPPED) ||
+ (statusType == GNUNET_OS_PROCESS_RUNNING) ) )
+ {
+ prev = pos;
+ continue;
+ }
+ if (statusType == GNUNET_OS_PROCESS_EXITED)
+ {
+ statstr = _( /* process termination method */ "exit");
+ statcode = statusCode;
+ }
+ else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
+ {
+ statstr = _( /* process termination method */ "signal");
+ statcode = statusCode;
+ }
else
- {
- statstr = _( /* process termination method */ "unknown");
- statcode = 0;
- }
+ {
+ statstr = _( /* process termination method */ "unknown");
+ statcode = 0;
+ }
if (NULL != pos->kill_continuation)
{
- pos->kill_continuation (pos->kill_continuation_cls, pos);
- }
- else
- {
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- _
- ("Service `%s' terminated with status %s/%d, will try to restart it!\n"),
- pos->name, statstr, statcode);
- /* schedule restart */
- pos->pid = 0;
+ if (prev == NULL)
+ running = next;
+ else
+ prev->next = next;
+ pos->kill_continuation (pos->kill_continuation_cls, pos);
+ continue;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ _("Service `%s' terminated with status %s/%d, will try to restart it!\n"),
+ pos->name, statstr, statcode);
+ /* schedule restart */
+ pos->pid = 0;
+ prev = pos;
}
/* check for services that need to be restarted due to
if ((0 == STAT (pos->config, &sbuf)) && (pos->mtime < sbuf.st_mtime))
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- _
- ("Restarting service `%s' due to configuration file change.\n"));
+ _("Restarting service `%s' due to configuration file change.\n"));
if (0 != PLIBC_KILL (pos->pid, SIGTERM))
GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
}
run (void *cls,
struct GNUNET_SCHEDULER_Handle *s,
struct GNUNET_SERVER_Handle *server,
- struct GNUNET_CONFIGURATION_Handle *c)
+ const struct GNUNET_CONFIGURATION_Handle *c)
{
char *defaultservices;
char *pos;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting...\n");
cfg = c;
sched = s;
if (GNUNET_OK !=
pos = strtok (defaultservices, " ");
while (pos != NULL)
{
- start_service (server, NULL, pos);
+ start_service (NULL, pos);
pos = strtok (NULL, " ");
}
GNUNET_free (defaultservices);
GNUNET_SCHEDULER_add_delayed (sched,
GNUNET_YES,
GNUNET_SCHEDULER_PRIORITY_IDLE,
- GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
+ GNUNET_SCHEDULER_NO_TASK,
MAINT_FREQUENCY, &maint, NULL);
}