1  /* Verify that the parent pid is unchanged by __clone_internal.
       2     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <sched.h>
      20  #include <signal.h>
      21  #include <string.h>
      22  #include <stdio.h>
      23  #include <unistd.h>
      24  #include <sys/types.h>
      25  #include <sys/wait.h>
      26  #include <clone_internal.h>
      27  #include <support/xunistd.h>
      28  
      29  #ifndef TEST_CLONE_FLAGS
      30  #define TEST_CLONE_FLAGS 0
      31  #endif
      32  
      33  static int sig;
      34  
      35  static int
      36  f (void *a)
      37  {
      38    puts ("in f");
      39    union sigval sival;
      40    sival.sival_int = getpid ();
      41    printf ("pid = %d\n", sival.sival_int);
      42    if (sigqueue (getppid (), sig, sival) != 0)
      43      return 1;
      44    return 0;
      45  }
      46  
      47  
      48  static int
      49  do_test (void)
      50  {
      51    int mypid = getpid ();
      52  
      53    sig = SIGRTMIN;
      54    sigset_t ss;
      55    sigemptyset (&ss);
      56    sigaddset (&ss, sig);
      57    if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
      58      {
      59        printf ("sigprocmask failed: %m\n");
      60        return 1;
      61      }
      62  
      63  #ifdef __ia64__
      64  # define STACK_SIZE 256 * 1024
      65  #else
      66  # define STACK_SIZE 128 * 1024
      67  #endif
      68    char st[STACK_SIZE] __attribute__ ((aligned));
      69    struct clone_args clone_args =
      70      {
      71        .flags = TEST_CLONE_FLAGS & ~CSIGNAL,
      72        .exit_signal = TEST_CLONE_FLAGS & CSIGNAL,
      73        .stack = (uintptr_t) st,
      74        .stack_size = sizeof (st),
      75      };
      76    pid_t p = __clone_internal (&clone_args, f, 0);
      77    if (p == -1)
      78      {
      79        printf("clone failed: %m\n");
      80        return 1;
      81      }
      82    printf ("new thread: %d\n", (int) p);
      83  
      84    siginfo_t si;
      85    do
      86      if (sigwaitinfo (&ss, &si) < 0)
      87        {
      88  	printf("sigwaitinfo failed: %m\n");
      89  	kill (p, SIGKILL);
      90  	return 1;
      91        }
      92    while  (si.si_signo != sig || si.si_code != SI_QUEUE);
      93  
      94    int e;
      95    xwaitpid (p, &e, __WCLONE);
      96    if (!WIFEXITED (e))
      97      {
      98        if (WIFSIGNALED (e))
      99  	printf ("died from signal %s\n", strsignal (WTERMSIG (e)));
     100        else
     101  	puts ("did not terminate correctly");
     102        return 1;
     103      }
     104    if (WEXITSTATUS (e) != 0)
     105      {
     106        printf ("exit code %d\n", WEXITSTATUS (e));
     107        return 1;
     108      }
     109  
     110    if (si.si_int != (int) p)
     111      {
     112        printf ("expected PID %d, got si_int %d\n", (int) p, si.si_int);
     113        kill (p, SIGKILL);
     114        return 1;
     115      }
     116  
     117    if (si.si_pid != p)
     118      {
     119        printf ("expected PID %d, got si_pid %d\n", (int) p, (int) si.si_pid);
     120        kill (p, SIGKILL);
     121        return 1;
     122      }
     123  
     124    if (getpid () != mypid)
     125      {
     126        puts ("my PID changed");
     127        return 1;
     128      }
     129  
     130    return 0;
     131  }
     132  
     133  #include <support/test-driver.c>