Blame posix/tst-waitid.c

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