(root)/
strace-6.5/
tests-m32/
attach-f-p.c
       1  /*
       2   * This file is part of attach-f-p strace test.
       3   *
       4   * Copyright (c) 2016-2018 Dmitry V. Levin <ldv@strace.io>
       5   * Copyright (c) 2016-2021 The strace developers.
       6   * All rights reserved.
       7   *
       8   * SPDX-License-Identifier: GPL-2.0-or-later
       9   */
      10  
      11  #include "tests.h"
      12  #include <assert.h>
      13  #include <errno.h>
      14  #include <pthread.h>
      15  #include <stdio.h>
      16  #include <stdlib.h>
      17  #include <sys/stat.h>
      18  #include "scno.h"
      19  #include <unistd.h>
      20  
      21  #define N 3
      22  
      23  typedef union {
      24  	void *ptr;
      25  	pid_t pid;
      26  } retval_t;
      27  
      28  static const char text_parent[] = "attach-f-p.test parent";
      29  static const char *child[N] = {
      30  	"attach-f-p.test child 0",
      31  	"attach-f-p.test child 1",
      32  	"attach-f-p.test child 2"
      33  };
      34  typedef int pipefd[2];
      35  static pipefd pipes[N];
      36  
      37  static void *
      38  thread(void *a)
      39  {
      40  	unsigned int no = (long) a;
      41  	int i, rc;
      42  
      43  	while ((rc = read(pipes[no][0], &i, sizeof(i))) != (int) sizeof(i)) {
      44  		if (rc < 0 && errno == EINTR)
      45  			continue;
      46  		perror_msg_and_fail("read[%u]", no);
      47  	}
      48  	assert(chdir(child[no]) == -1);
      49  	retval_t retval = { .pid = syscall(__NR_gettid) };
      50  	return retval.ptr;
      51  }
      52  
      53  int
      54  main(void)
      55  {
      56  	pthread_t t[N];
      57  
      58  	if (write(1, "", 0) != 0)
      59  		perror_msg_and_fail("write");
      60  
      61  	for (unsigned int i = 0; i < N; ++i) {
      62  		if (pipe(pipes[i]))
      63  			perror_msg_and_fail("pipe");
      64  
      65  		errno = pthread_create(&t[i], NULL, thread, (void *) (long) i);
      66  		if (errno)
      67  			perror_msg_and_fail("pthread_create");
      68  	}
      69  
      70  	if (write(1, "\n", 1) != 1)
      71  		perror_msg_and_fail("write");
      72  
      73  	/* wait for the peer to write to stdout */
      74  	for (;;) {
      75  		struct stat st;
      76  
      77  		if (fstat(1, &st))
      78  			perror_msg_and_fail("fstat");
      79  		if (st.st_size >= 103)
      80  			break;
      81  	}
      82  
      83  	for (unsigned int i = 0; i < N; ++i) {
      84  		/* sleep a bit to let the tracer catch up */
      85  		sleep(1);
      86  		if (write(pipes[i][1], &i, sizeof(i)) != (int) sizeof(i))
      87  			perror_msg_and_fail("write[%u]", i);
      88  		retval_t retval;
      89  		errno = pthread_join(t[i], &retval.ptr);
      90  		if (errno)
      91  			perror_msg_and_fail("pthread_join");
      92  		errno = ENOENT;
      93  		printf("%-5d chdir(\"%s\") = %s\n"
      94  		       "%-5d +++ exited with 0 +++\n",
      95  		       retval.pid, child[i], sprintrc(-1), retval.pid);
      96  	}
      97  
      98  	/* sleep a bit more to let the tracer catch up */
      99  	sleep(1);
     100  
     101  	pid_t pid = getpid();
     102  	assert(chdir(text_parent) == -1);
     103  
     104  	printf("%-5d chdir(\"%s\") = -1 ENOENT (%m)\n"
     105  	       "%-5d +++ exited with 0 +++\n", pid, text_parent, pid);
     106  
     107  	return 0;
     108  }