1 | #include <stdio.h>
|
---|
2 | #include <unistd.h>
|
---|
3 | #include <string.h>
|
---|
4 | #include <process.h>
|
---|
5 | #include <sys/socket.h>
|
---|
6 | #include <sys/fcntl.h>
|
---|
7 | #include <errno.h>
|
---|
8 |
|
---|
9 | #ifdef USE_POLL
|
---|
10 | #include <sys/poll.h>
|
---|
11 | #else
|
---|
12 | #include <sys/select.h>
|
---|
13 | #endif
|
---|
14 |
|
---|
15 | //#define WORKAROUND
|
---|
16 |
|
---|
17 | #ifdef WORKAROUND
|
---|
18 | static void child_exit()
|
---|
19 | {
|
---|
20 | flushall();
|
---|
21 | }
|
---|
22 | #endif
|
---|
23 |
|
---|
24 | const char child_str[] = "I'm a real child, pid 0x%04x\n";
|
---|
25 |
|
---|
26 | int main_child()
|
---|
27 | {
|
---|
28 | #ifdef WORKAROUND
|
---|
29 | atexit(child_exit);
|
---|
30 | #endif
|
---|
31 |
|
---|
32 | printf(child_str, getpid());
|
---|
33 |
|
---|
34 | return 0x11;
|
---|
35 | }
|
---|
36 |
|
---|
37 | int main_parent(int argc, const char** argv)
|
---|
38 | {
|
---|
39 | int p[2];
|
---|
40 | int pid, status;
|
---|
41 | ssize_t n, cnt;
|
---|
42 | #ifdef USE_POLL
|
---|
43 | struct pollfd pfd;
|
---|
44 | #else
|
---|
45 | fd_set readfds;
|
---|
46 | #endif
|
---|
47 | char buf[128];
|
---|
48 |
|
---|
49 | if (socketpair(AF_UNIX, SOCK_STREAM, 0, p) < 0)
|
---|
50 | {
|
---|
51 | perror("socketpair");
|
---|
52 | return 1;
|
---|
53 | }
|
---|
54 |
|
---|
55 | pid = fork();
|
---|
56 | if (!pid)
|
---|
57 | {
|
---|
58 | // child
|
---|
59 |
|
---|
60 | dup2(p[1], 1);
|
---|
61 | close(p[0]);
|
---|
62 | close(p[1]);
|
---|
63 |
|
---|
64 | execlp(argv[0], argv[0], "child", NULL);
|
---|
65 | perror("exec");
|
---|
66 | return 1;
|
---|
67 | }
|
---|
68 |
|
---|
69 | // parent
|
---|
70 | if (pid < 0)
|
---|
71 | {
|
---|
72 | perror("fork");
|
---|
73 | return 1;
|
---|
74 | }
|
---|
75 |
|
---|
76 | close(p[1]);
|
---|
77 |
|
---|
78 | printf("child pid 0x%x\n", pid);
|
---|
79 |
|
---|
80 | cnt = 0;
|
---|
81 |
|
---|
82 | #ifdef USE_POLL
|
---|
83 | pfd.fd = p[0];
|
---|
84 | pfd.events = POLLIN;
|
---|
85 |
|
---|
86 | while (1)
|
---|
87 | {
|
---|
88 | if (poll(&pfd, 1, -1) < 0)
|
---|
89 | {
|
---|
90 | if (errno == EINTR)
|
---|
91 | continue;
|
---|
92 | perror("poll");
|
---|
93 | break;
|
---|
94 | }
|
---|
95 |
|
---|
96 | if (!(pfd.revents & (POLLOUT|POLLIN|POLLHUP|POLLERR|POLLNVAL)))
|
---|
97 | continue;
|
---|
98 |
|
---|
99 | n = read(pfd.fd, buf, sizeof(buf));
|
---|
100 | if (n <= 0)
|
---|
101 | {
|
---|
102 | close(pfd.fd);
|
---|
103 | if (n < 0)
|
---|
104 | perror("read");
|
---|
105 | break;
|
---|
106 | }
|
---|
107 | else
|
---|
108 | {
|
---|
109 | cnt += n;
|
---|
110 | printf("read %d bytes from child [%.*s]\n", n, n, buf);
|
---|
111 | }
|
---|
112 | }
|
---|
113 | #else
|
---|
114 | while (1)
|
---|
115 | {
|
---|
116 | fd_set readfds;
|
---|
117 | FD_ZERO(&readfds);
|
---|
118 | FD_SET(p[0], &readfds);
|
---|
119 |
|
---|
120 | if (select(p[0] + 1, &readfds, NULL, NULL, NULL) < 0)
|
---|
121 | {
|
---|
122 | if (errno == EINTR)
|
---|
123 | continue;
|
---|
124 | perror("select");
|
---|
125 | break;
|
---|
126 | }
|
---|
127 |
|
---|
128 | if (!FD_ISSET(p[0], &readfds))
|
---|
129 | continue;
|
---|
130 |
|
---|
131 | n = read(p[0], buf, sizeof(buf));
|
---|
132 | if (n <= 0)
|
---|
133 | {
|
---|
134 | close(p[0]);
|
---|
135 | if (n < 0)
|
---|
136 | perror("read");
|
---|
137 | break;
|
---|
138 | }
|
---|
139 | else
|
---|
140 | {
|
---|
141 | cnt += n;
|
---|
142 | printf("read %d bytes from child [%.*s]\n", n, n, buf);
|
---|
143 | }
|
---|
144 | }
|
---|
145 | #endif
|
---|
146 |
|
---|
147 | while ((pid = waitpid(-1, &status, 0)) < 0)
|
---|
148 | {
|
---|
149 | if (errno == EINTR)
|
---|
150 | continue;
|
---|
151 | else
|
---|
152 | {
|
---|
153 | perror("waitpid");
|
---|
154 | break;
|
---|
155 | }
|
---|
156 | }
|
---|
157 |
|
---|
158 | printf("child exit status 0x%x (pid 0x%x)\n", status, pid);
|
---|
159 |
|
---|
160 | if (cnt != (ssize_t)strlen(child_str))
|
---|
161 | {
|
---|
162 | printf("FAILED (read %d bytes from child instead of %d)\n", cnt, strlen(child_str));
|
---|
163 | return 1;
|
---|
164 | }
|
---|
165 |
|
---|
166 | printf("SUCCEEDED");
|
---|
167 | return 0;
|
---|
168 | }
|
---|
169 |
|
---|
170 | int main(int argc, const char** argv)
|
---|
171 | {
|
---|
172 | if (argc > 1)
|
---|
173 | return main_child();
|
---|
174 | return main_parent(argc, argv);
|
---|
175 | }
|
---|