예제 #1
0
static int sig_queueaction(FAR struct tcb_s *stcb, siginfo_t *info)
{
  FAR sigactq_t *sigact;
  FAR sigq_t    *sigq;
  irqstate_t     flags;
  int            ret = OK;

  sched_lock();
  DEBUGASSERT(stcb != NULL && stcb->group != NULL);

  /* Find the group sigaction associated with this signal */

  sigact = sig_findaction(stcb->group, info->si_signo);

  /* Check if a valid signal handler is available and if the signal is
   * unblocked.  NOTE:  There is no default action.
   */

  if ((sigact) && (sigact->act.sa_u._sa_sigaction))
    {
      /* Allocate a new element for the signal queue.  NOTE:
       * sig_allocatependingsigaction will force a system crash if it is
       * unable to allocate memory for the signal data */

      sigq = sig_allocatependingsigaction();
      if (!sigq)
        {
          ret = -ENOMEM;
        }
      else
        {
          /* Populate the new signal queue element */

          sigq->action.sighandler = sigact->act.sa_u._sa_sigaction;
          sigq->mask = sigact->act.sa_mask;
          memcpy(&sigq->info, info, sizeof(siginfo_t));

          /* Put it at the end of the pending signals list */

          flags = enter_critical_section();
          sq_addlast((FAR sq_entry_t *)sigq, &(stcb->sigpendactionq));
          leave_critical_section(flags);
        }
    }

  sched_unlock();
  return ret;
}
예제 #2
0
static int sig_queueaction(FAR _TCB *stcb, siginfo_t *info)
{
  FAR sigactq_t *sigact;
  FAR sigq_t    *sigq;
  irqstate_t     saved_state;
  int            ret = OK;

  sched_lock();

  /* Find the sigaction associated with this signal */

  sigact = sig_findaction(stcb, info->si_signo);

  /* Check if a valid signal handler is available and if the signal is
   * unblocked.  NOTE:  There is no default action.
   */

  if ((sigact) && (sigact->act.sa_u._sa_sigaction))
    {
      /* Allocate a new element for the signal queue.  NOTE: sig_allocatependingsigaction
       * will force a system crash if it is unable to allocate memory for the
       * signal data */

      sigq = sig_allocatependingsigaction();
      if (!sigq) ret = ERROR;
      else
        {
          /* Populate the new signal queue element */

           sigq->action.sighandler = sigact->act.sa_u._sa_sigaction;
           sigq->mask = sigact->act.sa_mask;
           memcpy(&sigq->info, info, sizeof(siginfo_t));

           /* Put it at the end of the pending signals list */

           saved_state = irqsave();
           sq_addlast((FAR sq_entry_t*)sigq, &(stcb->sigpendactionq));
           irqrestore(saved_state);
        }
    }

  sched_unlock();
  return ret;
}
예제 #3
0
int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact)
{
  FAR struct tcb_s *rtcb = (FAR struct tcb_s*)g_readytorun.head;
  FAR sigactq_t *sigact;

  /* Since sigactions can only be installed from the running thread of
   * execution, no special precautions should be necessary.
   */

  /* Verify the signal number */

  if (!GOOD_SIGNO(signo))
    {
      set_errno(EINVAL);
      return ERROR;
    }

  /* Find the signal in the sigactionq */

  sigact = sig_findaction(rtcb, signo);

  /* Return the old sigaction value if so requested */

  if (oact)
    {
      if (sigact)
        {
          COPY_SIGACTION(oact, &sigact->act);
        }
      else
        {
          /* There isn't an old value */

          oact->sa_u._sa_handler = NULL;
          oact->sa_mask = NULL_SIGNAL_SET;
          oact->sa_flags = 0;
        }
    }

  /* If the argument act is a null pointer, signal handling is unchanged;
   * thus, the call can be used to enquire about the current handling of
   * a given signal.
   */

  if (!act)
    {
      return OK;
    }

#if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS)

  /* Handle a special case.  Retention of child status can be suppressed
   * if signo == SIGCHLD and sa_flags == SA_NOCLDWAIT.
   *
   * POSIX.1 leaves it unspecified whether a SIGCHLD signal is generated
   * when a child process terminates.  In NuttX, a SIGCHLD signal is
   * generated in this case; but in some other implementations, it may not
   * be.
   */

  if (signo == SIGCHLD && (act->sa_flags & SA_NOCLDWAIT) != 0)
    {
      irqstate_t flags;

      /* We do require a critical section to muck with the TCB values that
       * can be modified by the child thread.
       */

      flags = irqsave();

      /* Mark that status should be not be retained */

      rtcb->group->tg_flags |= GROUP_FLAG_NOCLDWAIT;

      /* Free all pending exit status */

      group_removechildren(rtcb->group);
      irqrestore(flags);
    }
#endif

  /* Handle the case where no sigaction is supplied (SIG_IGN) */

  if (act->sa_u._sa_handler == SIG_IGN)
    {
      /* Do we still have a sigaction container from the previous setting? */

      if (sigact)
        {
          /* Yes.. Remove it from sigactionq */

          sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);

          /* And deallocate it */

          sig_releaseaction(sigact);
        }
    }

  /* A sigaction has been supplied */

  else
    {
      /* Do we still have a sigaction container from the previous setting?
       * If so, then re-use for the new signal action.
       */

      if (!sigact)
        {
          /* No.. Then we need to allocate one for the new action. */

          sigact = sig_allocateaction();

          /* An error has occurred if we could not allocate the sigaction */

          if (!sigact)
           {
              set_errno(ENOMEM);
              return ERROR;
           }

          /* Put the signal number in the queue entry */

          sigact->signo = (uint8_t)signo;

          /* Add the new sigaction to sigactionq */

          sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
        }

      /* Set the new sigaction */

      COPY_SIGACTION(&sigact->act, act);
    }

  return OK;
}
예제 #4
0
static int group_signal_handler(pid_t pid, FAR void *arg)
{
  FAR struct group_signal_s *info = (FAR struct group_signal_s *)arg;
  FAR struct tcb_s *tcb;
  FAR sigactq_t *sigact;
  int ret;

  DEBUGASSERT(info);

  /* Get the TCB associated with the group member */

  tcb = sched_gettcb(pid);
  DEBUGASSERT(tcb);
  if (tcb)
    {
      /* Set this one as the default if we have not already set the default. */

      if (!info->dtcb)
        {
          info->dtcb = tcb;
        }

      /* Is the thread waiting for this signal (in this case, the signal is
       * probably blocked).
       */

      if (sigismember(&tcb->sigwaitmask, info->siginfo->si_signo) && !info->atcb)
        {
          /* Yes.. This means that the task is suspended, waiting for this
           * signal to occur. Stop looking and use this TCB.  The
           * requirement is this:  If a task group receives a signal and
           * more than one thread is waiting on that signal, then one and
           * only one indeterminate thread out of that waiting group will
           * receive the signal.
           */

          ret = sig_tcbdispatch(tcb, info->siginfo);
          if (ret < 0)
            {
              return ret;
            }

          /* Limit to one thread */

          info->atcb = tcb;
          if (info->ptcb != NULL);
            {
              return 1; /* Terminate the search */
            }
        }

      /* Is this signal unblocked on this thread? */

      if (!sigismember(&tcb->sigprocmask, info->siginfo->si_signo) &&
          !info->ptcb && tcb != info->atcb)
        {
          /* Yes.. remember this TCB if we have not encountered any
           * other threads that have the signal unblocked.
           */

          if (!info->utcb)
            {
              info->utcb = tcb;
            }

          /* Is there also an action associated with the task? */

          sigact = sig_findaction(tcb, info->siginfo->si_signo);
          if (sigact)
            {
              /* Yes.. then use this thread.  The requirement is this:
               * If a task group receives a signal then one and only one
               * indeterminate thread in the task group which is not
               * blocking the signal will receive the signal.
               */

              ret = sig_tcbdispatch(tcb, info->siginfo);
              if (ret < 0)
                {
                  return ret;
                }

              /* Limit to one thread */

              info->ptcb = tcb;
              if (info->atcb != NULL)
                {
                  return 1; /* Terminate the search */
                }
            }
        }
    }

  return 0; /* Keep searching */
}
예제 #5
0
int sigaction(int signo, FAR const struct sigaction *act, FAR struct sigaction *oact)
{
  FAR _TCB      *rtcb = (FAR _TCB*)g_readytorun.head;
  FAR sigactq_t *sigact;
  int            ret = ERROR;  /* Assume failure */

  /* Since sigactions can only be installed from the running thread of
   * execution, no special precautions should be necessary.
   */

  /* Verify the signal */

  if (GOOD_SIGNO(signo))
    {
      ret = OK;  /* Assume success */

      /* Find the signal in the sigactionq */

      sigact = sig_findaction(rtcb, signo);

      /* Return the old sigaction value if so requested */

      if (oact)
        {
          if (sigact)
            {
              COPY_SIGACTION(oact, &sigact->act);
            }
          else
            {
              /* There isn't an old value */

              oact->sa_u._sa_handler = NULL;
              oact->sa_mask = NULL_SIGNAL_SET;
              oact->sa_flags = 0;
            }
        }

      /* If no sigaction was found, but one is needed, then
       * allocate one.
       */

      if (!sigact && act && act->sa_u._sa_handler)
        {
          sigact = sig_allocateaction();

          /* An error has occurred if we could not allocate the sigaction */

          if (!sigact)
            {
              ret = ERROR;
            }
          else
            {
              /* Put the signal number in the queue entry */

              sigact->signo = (uint8_t)signo;

              /* Add the new sigaction to sigactionq */

              sq_addlast((FAR sq_entry_t*)sigact, &rtcb->sigactionq);
            }
        }

      /* Set the new sigaction if so requested */

      if ((sigact) && (act))
        {
          /* Check if it is a request to install a new handler */

          if (act->sa_u._sa_handler)
            {
              COPY_SIGACTION(&sigact->act, act);
            }

          /* No.. It is a request to remove the old handler */

          else
            {
              /* Remove the old sigaction from sigactionq */

              sq_rem((FAR sq_entry_t*)sigact, &rtcb->sigactionq);

              /* And deallocate it */

              sig_releaseaction(sigact);
            }
        }
    }

  return ret;
}