Back to index

glibc  2.9
Defines | Functions
waitid.c File Reference
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stddef.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sysdep-cancel.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define __need_NULL
#define OUR_WAITID   do_waitid

Functions

static int OUR_WAITID (idtype_t idtype, id_t id, siginfo_t *infop, int options)
int __waitid (idtype_t idtype, id_t id, siginfo_t *infop, int options)

Define Documentation

#define __need_NULL

Definition at line 24 of file waitid.c.

#define OUR_WAITID   do_waitid

Definition at line 34 of file waitid.c.


Function Documentation

int __waitid ( idtype_t  idtype,
id_t  id,
siginfo_t *  infop,
int  options 
)

Definition at line 153 of file waitid.c.

{
  if (SINGLE_THREAD_P)
    return do_waitid (idtype, id, infop, options);

  int oldtype = LIBC_CANCEL_ASYNC ();

  int result = do_waitid (idtype, id, infop, options);

  LIBC_CANCEL_RESET (oldtype);

  return result;
}
static int OUR_WAITID ( idtype_t  idtype,
id_t  id,
siginfo_t *  infop,
int  options 
) [static]

Definition at line 39 of file waitid.c.

{
  pid_t pid, child;
  int status;

  switch (idtype)
    {
    case P_PID:
      if(id <= 0)
       goto invalid;
      pid = (pid_t) id;
      break;
    case P_PGID:
      if (id < 0 || id == 1)
       goto invalid;
      pid = (pid_t) -id;
      break;
    case P_ALL:
      pid = -1;
      break;
    default:
    invalid:
      __set_errno (EINVAL);
      return -1;
    }

  /* Technically we're supposed to return EFAULT if infop is bogus,
     but that would involve mucking with signals, which is
     too much hassle.  User will have to deal with SIGSEGV/SIGBUS.
     We just check for a null pointer. */

  if (infop == NULL)
    {
      __set_errno (EFAULT);
      return -1;
    }

  /* This emulation using waitpid cannot support the waitid modes in which
     we do not reap the child, or match only stopped and not dead children.  */
  if (0
#ifdef WNOWAIT
      || (options & WNOWAIT)
#endif
#ifdef WEXITED
      || ((options & (WEXITED|WSTOPPED|WCONTINUED))
         != (WEXITED | (options & WUNTRACED)))
#endif
      )
    {
      __set_errno (ENOTSUP);
      return -1;
    }

  /* Note the waitid() is a cancellation point.  But since we call
     waitpid() which itself is a cancellation point we do not have
     to do anything here.  */
  child = __waitpid (pid, &status,
                   options
#ifdef WEXITED
                   &~ WEXITED
#endif
                   );

  if (child == -1)
    /* `waitpid' set `errno' for us.  */
    return -1;

  if (child == 0)
    {
      /* The WHOHANG bit in OPTIONS is set and there are children available
        but none has a status for us.  The XPG docs do not mention this
        case so we clear the `siginfo_t' struct and return successfully.  */
      infop->si_signo = 0;
      infop->si_code = 0;
      return 0;
    }

  /* Decode the status field and set infop members... */
  infop->si_signo = SIGCHLD;
  infop->si_pid = child;
  infop->si_errno = 0;

  if (WIFEXITED (status))
    {
      infop->si_code = CLD_EXITED;
      infop->si_status = WEXITSTATUS (status);
    }
  else if (WIFSIGNALED (status))
    {
      infop->si_code = WCOREDUMP (status) ? CLD_DUMPED : CLD_KILLED;
      infop->si_status = WTERMSIG (status);
    }
  else if (WIFSTOPPED (status))
    {
      infop->si_code = CLD_STOPPED;
      infop->si_status = WSTOPSIG (status);
    }
#ifdef WIFCONTINUED
  else if (WIFCONTINUED (status))
    {
      infop->si_code = CLD_CONTINUED;
      infop->si_status = SIGCONT;
    }
#endif
  else
    /* Can't happen. */
    assert (! "What?");

  return 0;
}

Here is the call graph for this function: