(root)/
strace-6.5/
tests/
get_process_reaper.c
       1  /*
       2   * Print the process reaper id.
       3   *
       4   * Copyright (c) 2020 Dmitry V. Levin <ldv@strace.io>
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  #include <stdio.h>
      12  #include <unistd.h>
      13  #include <sys/wait.h>
      14  
      15  /* PARENT - CHILD - GRANDCHILD */
      16  
      17  static int
      18  grandchild(int read_fd, int write_fd)
      19  {
      20  	/* wait for notification from PARENT about CHILD completion */
      21  	pid_t pid;
      22  	if (read(read_fd, &pid, sizeof(pid)) != 0)
      23  		perror_msg_and_fail("read");
      24  
      25  	/* write ppid to PARENT */
      26  	pid = getppid();
      27  	if (write(write_fd, &pid, sizeof(pid)) != sizeof(pid))
      28  		perror_msg_and_fail("write");
      29  
      30  	_exit(0);
      31  }
      32  
      33  static int
      34  child(int read_fd, int write_fd)
      35  {
      36  	pid_t pid = fork();
      37  	if (pid < 0)
      38  		perror_msg_and_fail("fork");
      39  
      40  	if (!pid)
      41  		return grandchild(read_fd, write_fd);
      42  	else
      43  		_exit(0);
      44  }
      45  
      46  static int
      47  parent(pid_t pid, int read_fd, int write_fd)
      48  {
      49  	/* wait for CHILD completion */
      50  	int status;
      51  	if (waitpid(pid, &status, 0) != pid)
      52  		perror_msg_and_fail("waitpid");
      53  	if (status != 0)
      54  		error_msg_and_fail("status %x", status);
      55  
      56  	/* notify GRANDCHILD about CHILD completion */
      57  	close(write_fd),
      58  	      write_fd = -1;
      59  
      60  	/* read ppid of GRANDCHILD */
      61  	if (read(read_fd, &pid, sizeof(pid)) != sizeof(pid))
      62  		perror_msg_and_fail("read");
      63  
      64  	printf("%d\n", pid);
      65  	return 0;
      66  }
      67  
      68  int
      69  main(void)
      70  {
      71  	int parent_grandchild_fds[2];
      72  #define parent_read_fd		parent_grandchild_fds[0]
      73  #define grandchild_write_fd	parent_grandchild_fds[1]
      74  
      75  	int grandchild_parent_fds[2];
      76  #define grandchild_read_fd	grandchild_parent_fds[0]
      77  #define parent_write_fd		grandchild_parent_fds[1]
      78  
      79  	if (pipe(parent_grandchild_fds) ||
      80  	    pipe(grandchild_parent_fds))
      81  		perror_msg_and_fail("pipe");
      82  
      83  	pid_t pid = fork();
      84  	if (pid < 0)
      85  		perror_msg_and_fail("fork");
      86  
      87  	if (!pid) {
      88  		/* CHILD */
      89  		close(parent_read_fd),
      90  		      parent_read_fd = -1;
      91  
      92  		close(parent_write_fd),
      93  		      parent_write_fd = -1;
      94  
      95  		return child(grandchild_read_fd,
      96  			     grandchild_write_fd);
      97  	} else {
      98  		/* PARENT */
      99  		close(grandchild_read_fd),
     100  		      grandchild_read_fd = -1;
     101  
     102  		close(grandchild_write_fd),
     103  		      grandchild_write_fd = -1;
     104  
     105  		return parent(pid, parent_read_fd,
     106  				   parent_write_fd);
     107  	}
     108  }