(root)/
glibc-2.38/
sysdeps/
pthread/
tst-exec2.c
       1  /* Thread with running thread calls exec.
       2     Copyright (C) 2002-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 <errno.h>
      20  #include <paths.h>
      21  #include <pthread.h>
      22  #include <signal.h>
      23  #include <spawn.h>
      24  #include <stdbool.h>
      25  #include <stdio.h>
      26  #include <stdlib.h>
      27  #include <unistd.h>
      28  #include <sys/wait.h>
      29  #include <support/xsignal.h>
      30  
      31  
      32  static void *
      33  tf (void *arg)
      34  {
      35    pthread_t th = (pthread_t) arg;
      36  
      37    if (pthread_join (th, NULL) == 0)
      38      {
      39        puts ("thread in parent joined!?");
      40        exit (1);
      41      }
      42  
      43    puts ("join in thread in parent returned!?");
      44    exit (1);
      45  }
      46  
      47  
      48  static int
      49  do_test (void)
      50  {
      51    int fd[2];
      52    if (pipe (fd) != 0)
      53      {
      54        puts ("pipe failed");
      55        exit (1);
      56      }
      57  
      58    /* Not interested in knowing when the pipe is closed.  */
      59    xsignal (SIGPIPE, SIG_IGN);
      60  
      61    pid_t pid = fork ();
      62    if (pid == -1)
      63      {
      64        puts ("fork failed");
      65        exit (1);
      66      }
      67  
      68    if (pid == 0)
      69      {
      70        /* Use the fd for stdout.  This is kind of ugly because it
      71  	 substitutes the fd of stdout but we know what we are doing
      72  	 here...  */
      73        if (dup2 (fd[1], STDOUT_FILENO) != STDOUT_FILENO)
      74  	{
      75  	  puts ("dup2 failed");
      76  	  exit (1);
      77  	}
      78  
      79        close (fd[0]);
      80  
      81        pthread_t th;
      82        if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
      83  	{
      84  	  puts ("create failed");
      85  	  exit (1);
      86  	}
      87  
      88        execl (_PATH_BSHELL, _PATH_BSHELL, "-c", "echo $$", NULL);
      89  
      90        puts ("execl failed");
      91        exit (1);
      92      }
      93  
      94    close (fd[1]);
      95  
      96    char buf[200];
      97    ssize_t n;
      98    bool seen_pid = false;
      99    while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
     100      {
     101        /* We only expect to read the PID.  */
     102        char *endp;
     103        long int rpid = strtol (buf, &endp, 10);
     104  
     105        if (*endp != '\n')
     106  	{
     107  	  printf ("didn't parse whole line: \"%s\"\n", buf);
     108  	  exit (1);
     109  	}
     110        if (endp == buf)
     111  	{
     112  	  puts ("read empty line");
     113  	  exit (1);
     114  	}
     115  
     116        if (rpid != pid)
     117  	{
     118  	  printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
     119  	  exit (1);
     120  	}
     121  
     122        if (seen_pid)
     123  	{
     124  	  puts ("found more than one PID line");
     125  	  exit (1);
     126  	}
     127        seen_pid = true;
     128      }
     129  
     130    close (fd[0]);
     131  
     132    int status;
     133    int err = waitpid (pid, &status, 0);
     134    if (err != pid)
     135      {
     136        puts ("waitpid failed");
     137        exit (1);
     138      }
     139  
     140    if (!seen_pid)
     141      {
     142        puts ("didn't get PID");
     143        exit (1);
     144      }
     145  
     146    return 0;
     147  }
     148  
     149  #define TEST_FUNCTION do_test ()
     150  #include "../test-skeleton.c"