Ejemplo n.º 1
0
void task_exithook(FAR _TCB *tcb, int status)
{
  /* Under certain conditions, task_exithook() can be called multiple times.
   * A bit in the TCB was set the first time this function was called.  If
   * that bit is set, then just ext doing nothing more..
   */

  if ((tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0)
    {
      return;
    }

  /* If exit function(s) were registered, call them now before we do any un-
   * initialization.  NOTE:  In the case of task_delete(), the exit function
   * will *not* be called on the thread execution of the task being deleted!
   */

  task_atexit(tcb);

  /* Call any registered on_exit function(s) */

  task_onexit(tcb, status);

  /* Leave the task group */

  task_leavegroup(tcb, status);

  /* Wakeup any tasks waiting for this task to exit */

  task_exitwakeup(tcb, status);

  /* Flush all streams (File descriptors will be closed when
   * the TCB is deallocated).
   */

#if CONFIG_NFILE_STREAMS > 0
  (void)lib_flushall(&tcb->group->tg_streamlist);
#endif

  /* Leave the task group.  Perhaps discarding any un-reaped child
   * status (no zombies here!)
   */

#ifdef HAVE_TASK_GROUP
  group_leave(tcb);
#endif

  /* Deallocate anything left in the TCB's queues */

#ifndef CONFIG_DISABLE_SIGNALS
  sig_cleanup(tcb); /* Deallocate Signal lists */
#endif

  /* This function can be re-entered in certain cases.  Set a flag
   * bit in the TCB to not that we have already completed this exit
   * processing.
   */

  tcb->flags |= TCB_FLAG_EXIT_PROCESSING;
}
Ejemplo n.º 2
0
static void purge_empty_groups(Tox *m)
{
    uint32_t i;

    for (i = 0; i < Tox_Bot.chats_idx; ++i) {
        if (!Tox_Bot.g_chats[i].active)
            continue;

        int num_peers = tox_group_number_peers(m, Tox_Bot.g_chats[i].num);

        if (num_peers <= 1) {
            fprintf(stderr, "Deleting empty group %i\n", Tox_Bot.g_chats[i].num);
            tox_del_groupchat(m, i);
            group_leave(i);
        }
    }
}
Ejemplo n.º 3
0
static void cmd_leave(Tox *m, uint32_t friendnum, int argc, char (*argv)[MAX_COMMAND_LENGTH])
{
    const char *outmsg = NULL;

    if (!friend_is_master(m, friendnum)) {
        authent_failed(m, friendnum);
        return;
    }

    if (argc < 1) {
        outmsg = "Error: Group number required";
        tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL);
        return;
    }

    int groupnum = atoi(argv[1]);

    if (groupnum == 0 && strcmp(argv[1], "0")) {
        outmsg = "Error: Invalid group number";
        tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL);
        return;
    }

    if (!tox_conference_delete(m, groupnum, NULL)) {
        outmsg = "Error: Invalid group number";
        tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) outmsg, strlen(outmsg), NULL);
        return;
    }

    char msg[MAX_COMMAND_LENGTH];

    char name[TOX_MAX_NAME_LENGTH];
    tox_friend_get_name(m, friendnum, (uint8_t *) name, NULL);
    size_t len = tox_friend_get_name_size(m, friendnum, NULL);
    name[len] = '\0';

    group_leave(groupnum);

    printf("Left group %d (%s)\n", groupnum, name);
    snprintf(msg, sizeof(msg), "Left group %d", groupnum);
    tox_friend_send_message(m, friendnum, TOX_MESSAGE_TYPE_NORMAL, (uint8_t *) msg, strlen(msg), NULL);
}
Ejemplo n.º 4
0
int task_init(FAR struct tcb_s *tcb, const char *name, int priority,
              FAR uint32_t *stack, uint32_t stack_size,
              main_t entry, FAR char * const argv[])
{
  FAR struct task_tcb_s *ttcb = (FAR struct task_tcb_s *)tcb;
  int errcode;
  int ret;

  /* Only tasks and kernel threads can be initialized in this way */

#ifndef CONFIG_DISABLE_PTHREAD
  DEBUGASSERT(tcb &&
             (tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_PTHREAD);
#endif

  /* Create a new task group */

#ifdef HAVE_TASK_GROUP
  ret = group_allocate(ttcb, tcb->flags);
  if (ret < 0)
    {
      errcode = -ret;
      goto errout;
    }
#endif

  /* Associate file descriptors with the new task */

#if CONFIG_NFILE_DESCRIPTORS > 0 || CONFIG_NSOCKET_DESCRIPTORS > 0
  ret = group_setuptaskfiles(ttcb);
  if (ret < 0)
    {
      errcode = -ret;
      goto errout_with_group;
    }
#endif

  /* Configure the user provided stack region */

  up_use_stack(tcb, stack, stack_size);

  /* Initialize the task control block */

  ret = task_schedsetup(ttcb, priority, task_start, entry,
                        TCB_FLAG_TTYPE_TASK);
  if (ret < OK)
    {
      errcode = -ret;
      goto errout_with_group;
    }

  /* Setup to pass parameters to the new task */

  (void)task_argsetup(ttcb, name, argv);

  /* Now we have enough in place that we can join the group */

#ifdef HAVE_TASK_GROUP
  ret = group_initialize(ttcb);
  if (ret < 0)
    {
      errcode = -ret;
      goto errout_with_group;
    }
#endif
  return OK;

errout_with_group:
#ifdef HAVE_TASK_GROUP
  group_leave(tcb);

errout:
#endif
  set_errno(errcode);
  return ERROR;
}
Ejemplo n.º 5
0
void task_exithook(FAR struct tcb_s *tcb, int status, bool nonblocking)
{
  /* Under certain conditions, task_exithook() can be called multiple times.
   * A bit in the TCB was set the first time this function was called.  If
   * that bit is set, then just exit doing nothing more..
   */

  if ((tcb->flags & TCB_FLAG_EXIT_PROCESSING) != 0)
    {
      return;
    }

#if defined(CONFIG_SCHED_ATEXIT) || defined(CONFIG_SCHED_ONEXIT)
  /* If exit function(s) were registered, call them now before we do any un-
   * initialization.
   *
   * NOTES:
   *
   * 1. In the case of task_delete(), the exit function will *not* be called
   *    on the thread execution of the task being deleted!  That is probably
   *    a bug.
   * 2. We cannot call the exit functions if nonblocking is requested:  These
   *    functions might block.
   * 3. This function will only be called with with non-blocking == true
   *    only when called through _exit(). _exit() behaviors requires that
   *    the exit functions *not* be called.
   */

  if (!nonblocking)
    {
      task_atexit(tcb);

      /* Call any registered on_exit function(s) */

      task_onexit(tcb, status);
    }
#endif

  /* If the task was terminated by another task, it may be in an unknown
   * state.  Make some feeble effort to recover the state.
   */

  task_recover(tcb);

  /* Send the SIGCHILD signal to the parent task group */

  task_signalparent(tcb, status);

  /* Wakeup any tasks waiting for this task to exit */

  task_exitwakeup(tcb, status);

  /* If this is the last thread in the group, then flush all streams (File
   * descriptors will be closed when the TCB is deallocated).
   *
   * NOTES:
   * 1. We cannot flush the buffered I/O if nonblocking is requested.
   *    that might cause this logic to block.
   * 2. This function will only be called with with non-blocking == true
   *    only when called through _exit(). _exit() behavior does not
   *    require that the streams be flushed
   */

  if (!nonblocking)
    {
      task_flushstreams(tcb);
    }

#ifdef HAVE_TASK_GROUP
  /* Leave the task group.  Perhaps discarding any un-reaped child
   * status (no zombies here!)
   */

  group_leave(tcb);
#endif

#ifndef CONFIG_DISABLE_SIGNALS
  /* Deallocate anything left in the TCB's queues */

  sig_cleanup(tcb); /* Deallocate Signal lists */
#endif

  /* This function can be re-entered in certain cases.  Set a flag
   * bit in the TCB to not that we have already completed this exit
   * processing.
   */

  tcb->flags |= TCB_FLAG_EXIT_PROCESSING;
}