Blame posix/tst-waitid.c

Packit 6c4009
/* Tests for waitid.
Packit 6c4009
   Copyright (C) 2004-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <errno.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <sys/wait.h>
Packit 6c4009
#include <signal.h>
Packit 6c4009
Packit 6c4009
#define TIMEOUT 15
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
test_child (void)
Packit 6c4009
{
Packit 6c4009
  /* Wait a second to be sure the parent set his variables before we
Packit 6c4009
     produce a SIGCHLD.  */
Packit 6c4009
  sleep (1);
Packit 6c4009
Packit 6c4009
  /* First thing, we stop ourselves.  */
Packit 6c4009
  raise (SIGSTOP);
Packit 6c4009
Packit 6c4009
  /* Hey, we got continued!  */
Packit 6c4009
  while (1)
Packit 6c4009
    pause ();
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#ifndef WEXITED
Packit 6c4009
# define WEXITED	0
Packit 6c4009
# define WCONTINUED	0
Packit 6c4009
# define WSTOPPED	WUNTRACED
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
static sig_atomic_t expecting_sigchld, spurious_sigchld;
Packit 6c4009
#ifdef SA_SIGINFO
Packit 6c4009
static siginfo_t sigchld_info;
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
sigchld (int signo, siginfo_t *info, void *ctx)
Packit 6c4009
{
Packit 6c4009
  if (signo != SIGCHLD)
Packit 6c4009
    {
Packit 6c4009
      printf ("SIGCHLD handler got signal %d instead!\n", signo);
Packit 6c4009
      _exit (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (! expecting_sigchld)
Packit 6c4009
    {
Packit 6c4009
      spurious_sigchld = 1;
Packit 6c4009
      printf ("spurious SIGCHLD: signo %d code %d status %d pid %d\n",
Packit 6c4009
	      info->si_signo, info->si_code, info->si_status, info->si_pid);
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      sigchld_info = *info;
Packit 6c4009
      expecting_sigchld = 0;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static void
Packit 6c4009
check_sigchld (const char *phase, int *ok, int code, int status, pid_t pid)
Packit 6c4009
{
Packit 6c4009
  if (expecting_sigchld)
Packit 6c4009
    {
Packit 6c4009
      printf ("missing SIGCHLD on %s\n", phase);
Packit 6c4009
      *ok = EXIT_FAILURE;
Packit 6c4009
      expecting_sigchld = 0;
Packit 6c4009
      return;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  if (sigchld_info.si_signo != SIGCHLD)
Packit 6c4009
    {
Packit 6c4009
      printf ("SIGCHLD for %s signal %d\n", phase, sigchld_info.si_signo);
Packit 6c4009
      *ok = EXIT_FAILURE;
Packit 6c4009
    }
Packit 6c4009
  if (sigchld_info.si_code != code)
Packit 6c4009
    {
Packit 6c4009
      printf ("SIGCHLD for %s code %d\n", phase, sigchld_info.si_code);
Packit 6c4009
      *ok = EXIT_FAILURE;
Packit 6c4009
    }
Packit 6c4009
  if (sigchld_info.si_status != status)
Packit 6c4009
    {
Packit 6c4009
      printf ("SIGCHLD for %s status %d\n", phase, sigchld_info.si_status);
Packit 6c4009
      *ok = EXIT_FAILURE;
Packit 6c4009
    }
Packit 6c4009
  if (sigchld_info.si_pid != pid)
Packit 6c4009
    {
Packit 6c4009
      printf ("SIGCHLD for %s pid %d\n", phase, sigchld_info.si_pid);
Packit 6c4009
      *ok = EXIT_FAILURE;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
# define CHECK_SIGCHLD(phase, code_check, status_check) \
Packit 6c4009
  check_sigchld ((phase), &status, (code_check), (status_check), pid)
Packit 6c4009
#else
Packit 6c4009
# define CHECK_SIGCHLD(phase, code, status) ((void) 0)
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
static int
Packit 6c4009
do_test (int argc, char *argv[])
Packit 6c4009
{
Packit 6c4009
#ifdef SA_SIGINFO
Packit 6c4009
  struct sigaction sa;
Packit 6c4009
  sa.sa_flags = SA_SIGINFO|SA_RESTART;
Packit 6c4009
  sa.sa_sigaction = &sigchld;
Packit 6c4009
  if (sigemptyset (&sa.sa_mask) < 0 || sigaction (SIGCHLD, &sa, NULL) < 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("setting SIGCHLD handler: %m\n");
Packit 6c4009
      return EXIT_FAILURE;
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  expecting_sigchld = 1;
Packit 6c4009
Packit 6c4009
  pid_t pid = fork ();
Packit 6c4009
  if (pid < 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("fork: %m\n");
Packit 6c4009
      return EXIT_FAILURE;
Packit 6c4009
    }
Packit 6c4009
  else if (pid == 0)
Packit 6c4009
    {
Packit 6c4009
      test_child ();
Packit 6c4009
      _exit (127);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  int status = EXIT_SUCCESS;
Packit 6c4009
#define RETURN(ok) \
Packit 6c4009
    do { if (status == EXIT_SUCCESS) status = (ok); goto out; } while (0)
Packit 6c4009
Packit 6c4009
  /* Give the child a chance to stop.  */
Packit 6c4009
  sleep (3);
Packit 6c4009
Packit 6c4009
  CHECK_SIGCHLD ("stopped (before waitid)", CLD_STOPPED, SIGSTOP);
Packit 6c4009
Packit 6c4009
  /* Now try a wait that should not succeed.  */
Packit 6c4009
  siginfo_t info;
Packit 6c4009
  info.si_signo = 0;		/* A successful call sets it to SIGCHLD.  */
Packit 6c4009
  int fail = waitid (P_PID, pid, &info, WEXITED|WCONTINUED|WNOHANG);
Packit 6c4009
  switch (fail)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      printf ("waitid returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case -1:
Packit 6c4009
      printf ("waitid WNOHANG on stopped: %m\n");
Packit 6c4009
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
Packit 6c4009
    case 0:
Packit 6c4009
      if (info.si_signo == 0)
Packit 6c4009
	break;
Packit 6c4009
      if (info.si_signo == SIGCHLD)
Packit 6c4009
	printf ("waitid WNOHANG on stopped status %d\n", info.si_status);
Packit 6c4009
      else
Packit 6c4009
	printf ("waitid WNOHANG on stopped signal %d\n", info.si_signo);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Next the wait that should succeed right away.  */
Packit 6c4009
  info.si_signo = 0;		/* A successful call sets it to SIGCHLD.  */
Packit 6c4009
  info.si_pid = -1;
Packit 6c4009
  info.si_status = -1;
Packit 6c4009
  fail = waitid (P_PID, pid, &info, WSTOPPED|WNOHANG);
Packit 6c4009
  switch (fail)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      printf ("waitid WSTOPPED|WNOHANG returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case -1:
Packit 6c4009
      printf ("waitid WSTOPPED|WNOHANG on stopped: %m\n");
Packit 6c4009
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
Packit 6c4009
    case 0:
Packit 6c4009
      if (info.si_signo != SIGCHLD)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WSTOPPED|WNOHANG on stopped signal %d\n",
Packit 6c4009
		  info.si_signo);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_code != CLD_STOPPED)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WSTOPPED|WNOHANG on stopped code %d\n",
Packit 6c4009
		  info.si_code);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_status != SIGSTOP)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WSTOPPED|WNOHANG on stopped status %d\n",
Packit 6c4009
		  info.si_status);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_pid != pid)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WSTOPPED|WNOHANG on stopped pid %d != %d\n",
Packit 6c4009
		  info.si_pid, pid);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  expecting_sigchld = WCONTINUED != 0;
Packit 6c4009
Packit 6c4009
  if (kill (pid, SIGCONT) != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("kill (%d, SIGCONT): %m\n", pid);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Wait for the child to have continued.  */
Packit 6c4009
  sleep (2);
Packit 6c4009
Packit 6c4009
#if WCONTINUED != 0
Packit 6c4009
  if (expecting_sigchld)
Packit 6c4009
    {
Packit 6c4009
      printf ("no SIGCHLD seen for SIGCONT (optional)\n");
Packit 6c4009
      expecting_sigchld = 0;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    CHECK_SIGCHLD ("continued (before waitid)", CLD_CONTINUED, SIGCONT);
Packit 6c4009
Packit 6c4009
  info.si_signo = 0;		/* A successful call sets it to SIGCHLD.  */
Packit 6c4009
  info.si_pid = -1;
Packit 6c4009
  info.si_status = -1;
Packit 6c4009
  fail = waitid (P_PID, pid, &info, WCONTINUED|WNOWAIT);
Packit 6c4009
  switch (fail)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      printf ("waitid WCONTINUED|WNOWAIT returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case -1:
Packit 6c4009
      printf ("waitid WCONTINUED|WNOWAIT on continued: %m\n");
Packit 6c4009
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
Packit 6c4009
    case 0:
Packit 6c4009
      if (info.si_signo != SIGCHLD)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED|WNOWAIT on continued signal %d\n",
Packit 6c4009
		  info.si_signo);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_code != CLD_CONTINUED)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED|WNOWAIT on continued code %d\n",
Packit 6c4009
		  info.si_code);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_status != SIGCONT)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED|WNOWAIT on continued status %d\n",
Packit 6c4009
		  info.si_status);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_pid != pid)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED|WNOWAIT on continued pid %d != %d\n",
Packit 6c4009
		  info.si_pid, pid);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* That should leave the CLD_CONTINUED state waiting to be seen again.  */
Packit 6c4009
  info.si_signo = 0;		/* A successful call sets it to SIGCHLD.  */
Packit 6c4009
  info.si_pid = -1;
Packit 6c4009
  info.si_status = -1;
Packit 6c4009
  fail = waitid (P_PID, pid, &info, WCONTINUED);
Packit 6c4009
  switch (fail)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      printf ("waitid WCONTINUED returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case -1:
Packit 6c4009
      printf ("waitid WCONTINUED on continued: %m\n");
Packit 6c4009
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
Packit 6c4009
    case 0:
Packit 6c4009
      if (info.si_signo != SIGCHLD)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED on continued signal %d\n", info.si_signo);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_code != CLD_CONTINUED)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED on continued code %d\n", info.si_code);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_status != SIGCONT)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED on continued status %d\n",
Packit 6c4009
		  info.si_status);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_pid != pid)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WCONTINUED on continued pid %d != %d\n",
Packit 6c4009
		  info.si_pid, pid);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Now try a wait that should not succeed.  */
Packit 6c4009
  info.si_signo = 0;		/* A successful call sets it to SIGCHLD.  */
Packit 6c4009
  fail = waitid (P_PID, pid, &info, WCONTINUED|WNOHANG);
Packit 6c4009
  switch (fail)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      printf ("waitid returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case -1:
Packit 6c4009
      printf ("waitid WCONTINUED|WNOHANG on waited continued: %m\n");
Packit 6c4009
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
Packit 6c4009
    case 0:
Packit 6c4009
      if (info.si_signo == 0)
Packit 6c4009
	break;
Packit 6c4009
      if (info.si_signo == SIGCHLD)
Packit 6c4009
	printf ("waitid WCONTINUED|WNOHANG on waited continued status %d\n",
Packit 6c4009
		info.si_status);
Packit 6c4009
      else
Packit 6c4009
	printf ("waitid WCONTINUED|WNOHANG on waited continued signal %d\n",
Packit 6c4009
		info.si_signo);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Now stop him again and test waitpid with WCONTINUED.  */
Packit 6c4009
  expecting_sigchld = 1;
Packit 6c4009
  if (kill (pid, SIGSTOP) != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("kill (%d, SIGSTOP): %m\n", pid);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Give the child a chance to stop.  The waitpid call below will block
Packit 6c4009
     until it has stopped, but if we are real quick and enter the waitpid
Packit 6c4009
     system call before the SIGCHLD has been generated, then it will be
Packit 6c4009
     discarded and never delivered.  */
Packit 6c4009
  sleep (3);
Packit 6c4009
Packit 6c4009
  pid_t wpid = waitpid (pid, &fail, WUNTRACED);
Packit 6c4009
  if (wpid < 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("waitpid WUNTRACED on stopped: %m\n");
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
  else if (wpid != pid)
Packit 6c4009
    {
Packit 6c4009
      printf ("waitpid WUNTRACED on stopped returned %d != %d (status %x)\n",
Packit 6c4009
	      wpid, pid, fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
  else if (!WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail)
Packit 6c4009
	   || WIFCONTINUED (fail) || WSTOPSIG (fail) != SIGSTOP)
Packit 6c4009
    {
Packit 6c4009
      printf ("waitpid WUNTRACED on stopped: status %x\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
  CHECK_SIGCHLD ("stopped (after waitpid)", CLD_STOPPED, SIGSTOP);
Packit 6c4009
Packit 6c4009
  expecting_sigchld = 1;
Packit 6c4009
  if (kill (pid, SIGCONT) != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("kill (%d, SIGCONT): %m\n", pid);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  /* Wait for the child to have continued.  */
Packit 6c4009
  sleep (2);
Packit 6c4009
Packit 6c4009
  if (expecting_sigchld)
Packit 6c4009
    {
Packit 6c4009
      printf ("no SIGCHLD seen for SIGCONT (optional)\n");
Packit 6c4009
      expecting_sigchld = 0;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    CHECK_SIGCHLD ("continued (before waitpid)", CLD_CONTINUED, SIGCONT);
Packit 6c4009
Packit 6c4009
  wpid = waitpid (pid, &fail, WCONTINUED);
Packit 6c4009
  if (wpid < 0)
Packit 6c4009
    {
Packit 6c4009
      if (errno == EINVAL)
Packit 6c4009
	printf ("waitpid does not support WCONTINUED\n");
Packit 6c4009
      else
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitpid WCONTINUED on continued: %m\n");
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else if (wpid != pid)
Packit 6c4009
    {
Packit 6c4009
      printf ("\
Packit 6c4009
waitpid WCONTINUED on continued returned %d != %d (status %x)\n",
Packit 6c4009
	     wpid, pid, fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
  else if (WIFSTOPPED (fail) || WIFSIGNALED (fail) || WIFEXITED (fail)
Packit 6c4009
	   || !WIFCONTINUED (fail))
Packit 6c4009
    {
Packit 6c4009
      printf ("waitpid WCONTINUED on continued: status %x\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  expecting_sigchld = 1;
Packit 6c4009
Packit 6c4009
  /* Die, child, die!  */
Packit 6c4009
  if (kill (pid, SIGKILL) != 0)
Packit 6c4009
    {
Packit 6c4009
      printf ("kill (%d, SIGKILL): %m\n", pid);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
#ifdef WNOWAIT
Packit 6c4009
  info.si_signo = 0;		/* A successful call sets it to SIGCHLD.  */
Packit 6c4009
  info.si_pid = -1;
Packit 6c4009
  info.si_status = -1;
Packit 6c4009
  fail = waitid (P_PID, pid, &info, WEXITED|WNOWAIT);
Packit 6c4009
  switch (fail)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      printf ("waitid WNOWAIT returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case -1:
Packit 6c4009
      printf ("waitid WNOWAIT on killed: %m\n");
Packit 6c4009
      RETURN (errno == ENOTSUP ? EXIT_SUCCESS : EXIT_FAILURE);
Packit 6c4009
    case 0:
Packit 6c4009
      if (info.si_signo != SIGCHLD)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOWAIT on killed signal %d\n", info.si_signo);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_code != CLD_KILLED)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOWAIT on killed code %d\n", info.si_code);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_status != SIGKILL)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOWAIT on killed status %d\n", info.si_status);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_pid != pid)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOWAIT on killed pid %d != %d\n", info.si_pid, pid);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
#else
Packit 6c4009
  /* Allow enough time to be sure the child died; we didn't synchronize.  */
Packit 6c4009
  sleep (2);
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
  CHECK_SIGCHLD ("killed", CLD_KILLED, SIGKILL);
Packit 6c4009
Packit 6c4009
  info.si_signo = 0;		/* A successful call sets it to SIGCHLD.  */
Packit 6c4009
  info.si_pid = -1;
Packit 6c4009
  info.si_status = -1;
Packit 6c4009
  fail = waitid (P_PID, pid, &info, WEXITED|WNOHANG);
Packit 6c4009
  switch (fail)
Packit 6c4009
    {
Packit 6c4009
    default:
Packit 6c4009
      printf ("waitid WNOHANG returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case -1:
Packit 6c4009
      printf ("waitid WNOHANG on killed: %m\n");
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    case 0:
Packit 6c4009
      if (info.si_signo != SIGCHLD)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOHANG on killed signal %d\n", info.si_signo);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_code != CLD_KILLED)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOHANG on killed code %d\n", info.si_code);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_status != SIGKILL)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOHANG on killed status %d\n", info.si_status);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
      if (info.si_pid != pid)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WNOHANG on killed pid %d != %d\n", info.si_pid, pid);
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  fail = waitid (P_PID, pid, &info, WEXITED);
Packit 6c4009
  if (fail == -1)
Packit 6c4009
    {
Packit 6c4009
      if (errno != ECHILD)
Packit 6c4009
	{
Packit 6c4009
	  printf ("waitid WEXITED on killed: %m\n");
Packit 6c4009
	  RETURN (EXIT_FAILURE);
Packit 6c4009
	}
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    {
Packit 6c4009
      printf ("waitid WEXITED returned bogus value %d\n", fail);
Packit 6c4009
      RETURN (EXIT_FAILURE);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
#undef RETURN
Packit 6c4009
 out:
Packit 6c4009
  if (spurious_sigchld)
Packit 6c4009
    status = EXIT_FAILURE;
Packit 6c4009
  signal (SIGCHLD, SIG_IGN);
Packit 6c4009
  kill (pid, SIGKILL);		/* Make sure it's dead if we bailed early.  */
Packit 6c4009
  return status;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
#include "../test-skeleton.c"