Exemplo n.º 1
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;
}
Exemplo n.º 2
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;
}