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