(root)/
glibc-2.38/
sysdeps/
pthread/
tst-exec1.c
       1  /* Simple exec test, only a thread in the parent.
       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    posix_spawn_file_actions_t a;
      62    if (posix_spawn_file_actions_init (&a) != 0)
      63      {
      64        puts ("spawn_file_actions_init failed");
      65        exit (1);
      66      }
      67  
      68    if (posix_spawn_file_actions_adddup2 (&a, fd[1], STDOUT_FILENO) != 0)
      69      {
      70        puts ("spawn_file_actions_adddup2 failed");
      71        exit (1);
      72      }
      73  
      74    if (posix_spawn_file_actions_addclose (&a, fd[0]) != 0)
      75      {
      76        puts ("spawn_file_actions_addclose");
      77        exit (1);
      78      }
      79  
      80    pthread_t th;
      81    if (pthread_create (&th, NULL, tf, (void *) pthread_self ()) != 0)
      82      {
      83        puts ("create failed");
      84        exit (1);
      85      }
      86  
      87    pid_t pid;
      88    char *argv[] = { (char *) _PATH_BSHELL, (char *) "-c", (char *) "echo $$",
      89  		   NULL };
      90    if (posix_spawn (&pid, _PATH_BSHELL, &a, NULL, argv, NULL) != 0)
      91      {
      92        puts ("spawn failed");
      93        exit (1);
      94      }
      95  
      96    close (fd[1]);
      97  
      98    char buf[200];
      99    ssize_t n;
     100    bool seen_pid = false;
     101    while (TEMP_FAILURE_RETRY ((n = read (fd[0], buf, sizeof (buf)))) > 0)
     102      {
     103        /* We only expect to read the PID.  */
     104        char *endp;
     105        long int rpid = strtol (buf, &endp, 10);
     106  
     107        if (*endp != '\n')
     108  	{
     109  	  printf ("didn't parse whole line: \"%s\"\n", buf);
     110  	  exit (1);
     111  	}
     112        if (endp == buf)
     113  	{
     114  	  puts ("read empty line");
     115  	  exit (1);
     116  	}
     117  
     118        if (rpid != pid)
     119  	{
     120  	  printf ("found \"%s\", expected PID %ld\n", buf, (long int) pid);
     121  	  exit (1);
     122  	}
     123  
     124        if (seen_pid)
     125  	{
     126  	  puts ("found more than one PID line");
     127  	  exit (1);
     128  	}
     129  
     130        seen_pid = true;
     131      }
     132  
     133    close (fd[0]);
     134  
     135    int status;
     136    int err = waitpid (pid, &status, 0);
     137    if (err != pid)
     138      {
     139        puts ("waitpid failed");
     140        exit (1);
     141      }
     142  
     143    if (!seen_pid)
     144      {
     145        puts ("didn't get PID");
     146        exit (1);
     147      }
     148  
     149    puts ("read correct PID");
     150  
     151    return 0;
     152  }
     153  
     154  #define TEST_FUNCTION do_test ()
     155  #include "../test-skeleton.c"