Пример #1
0
/**
 * Task triggered whenever we receive a SIGCHLD (child
 * process died).
 *
 * @param cls closure, NULL if we need to self-restart
 * @param tc context
 */
static void
child_death_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  const struct GNUNET_DISK_FileHandle *pr;
  char c[16];

  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
  child_death_task_id = NULL;
  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
  {
    child_death_task_id =
	GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
					pr, &child_death_task, NULL);
    return;
  }
  /* consume the signal */
  GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));
  LOG_DEBUG ("Child died\n");
  GNUNET_SCHEDULER_cancel (terminate_task_id);
  terminate_task_id = NULL;
  GNUNET_assert (GNUNET_OK == GNUNET_OS_process_status (child, &child_status,
                                                        &child_exit_code));
  GNUNET_OS_process_destroy (child);
  child = NULL;
  shutdown_task_id = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
}
Пример #2
0
/**
 * Task triggered whenever we receive a SIGCHLD (child
 * process died) or when user presses CTRL-C.
 *
 * @param cls closure, NULL
 * @param tc scheduler context
 */
static void
maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  enum GNUNET_OS_ProcessStatusType type;
  if ( (GNUNET_OK !=
	GNUNET_OS_process_status (p, &type, &exit_code)) ||
       (type != GNUNET_OS_PROCESS_EXITED) )
    GNUNET_break (0 == GNUNET_OS_process_kill (p, GNUNET_TERM_SIG));
  GNUNET_OS_process_destroy (p);
}
Пример #3
0
/**
 * Task for checking whether a host is habitable or not
 *
 * @param cls GNUNET_TESTBED_HostHabitableCheckHandle
 * @param tc the scheduler task context
 */
static void
habitability_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct GNUNET_TESTBED_HostHabitableCheckHandle *h = cls;
  void *cb_cls;
  GNUNET_TESTBED_HostHabitableCallback cb;
  const struct GNUNET_TESTBED_Host *host;
  unsigned long code;
  enum GNUNET_OS_ProcessStatusType type;
  int ret;

  h->habitability_check_task = NULL;
  ret = GNUNET_OS_process_status (h->auxp, &type, &code);
  if (GNUNET_SYSERR == ret)
  {
    GNUNET_break (0);
    ret = GNUNET_NO;
    goto call_cb;
  }
  if (GNUNET_NO == ret)
  {
    h->wait_time = GNUNET_TIME_STD_BACKOFF (h->wait_time);
    h->habitability_check_task =
        GNUNET_SCHEDULER_add_delayed (h->wait_time, &habitability_check, h);
    return;
  }
  GNUNET_OS_process_destroy (h->auxp);
  h->auxp = NULL;
  ret = (0 != code) ? GNUNET_NO : GNUNET_YES;

call_cb:
  if (NULL != h->auxp)
    GNUNET_OS_process_destroy (h->auxp);
  cb = h->cb;
  cb_cls = h->cb_cls;
  host = h->host;
  free_argv (h->helper_argv);
  GNUNET_free (h);
  if (NULL != cb)
    cb (cb_cls, host, ret);
}
Пример #4
0
/**
 * Task triggered whenever we receive a SIGCHLD (child
 * process died).
 *
 * @param cls closure, NULL if we need to self-restart
 * @param tc context
 */
static void
maint_child_death (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
{
  struct ServiceList *pos;
  struct ServiceList *next;
  struct ServiceListeningInfo *sli;
  const char *statstr;
  int statcode;
  int ret;
  char c[16];
  enum GNUNET_OS_ProcessStatusType statusType;
  unsigned long statusCode;
  const struct GNUNET_DISK_FileHandle *pr;

  pr = GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ);
  child_death_task = GNUNET_SCHEDULER_NO_TASK;
  if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_READ_READY))
    {
      /* shutdown scheduled us, ignore! */
      child_death_task =
	GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
					pr, &maint_child_death, NULL);
      return;
    }
  /* consume the signal */
  GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c)));

  /* check for services that died (WAITPID) */
  next = running_head;
  while (NULL != (pos = next))
    {
      next = pos->next;

      if (pos->proc == NULL)
      {
	if (GNUNET_YES == in_shutdown)
	  free_service (pos);
	continue;
      }
      if ((GNUNET_SYSERR ==
	   (ret =
	    GNUNET_OS_process_status (pos->proc, &statusType, &statusCode)))
	  || ((ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED)
	      || (statusType == GNUNET_OS_PROCESS_RUNNING)))
	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;
      }
      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)
	{
	  signal_result (pos->killing_client, pos->name,
			 GNUNET_ARM_PROCESS_DOWN);
	  GNUNET_SERVER_client_drop (pos->killing_client);
	  pos->killing_client = NULL;
	  /* process can still be re-started on-demand, ensure it is re-started if there is demand */
	  for (sli = pos->listen_head; NULL != sli; sli = sli->next)
	    {
	      GNUNET_break (GNUNET_SCHEDULER_NO_TASK == sli->accept_task);
	      sli->accept_task =
		GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
					       sli->listen_socket,
					       &accept_connection, sli);
	    }
	  continue;
	}
      if (GNUNET_YES != in_shutdown)
	{
	  if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
	    {
	      /* process terminated normally, allow restart at any time */
	      pos->restart_at.abs_value = 0;
	    }
          else
            {
	      if (0 == (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
	        GNUNET_log (GNUNET_ERROR_TYPE_INFO,
			    _
			    ("Service `%s' terminated with status %s/%d, will restart in %llu ms\n"),
			    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));
            }
	  if (GNUNET_SCHEDULER_NO_TASK != child_restart_task)
	    GNUNET_SCHEDULER_cancel (child_restart_task);
	  child_restart_task =
	    GNUNET_SCHEDULER_add_with_priority
	    (GNUNET_SCHEDULER_PRIORITY_IDLE, 
	     &delayed_restart_task, NULL);
	}
      else
	{
	  free_service (pos);
	}
    }
  child_death_task =
    GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
				    pr, &maint_child_death, NULL);
  if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
    do_shutdown ();
}