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 }