Ticket #374: fork_flush.c

File fork_flush.c, 2.6 KB (added by dmik, 8 years ago)
Line 
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
18static void child_exit()
19{
20 flushall();
21}
22#endif
23
24const char child_str[] = "I'm a real child, pid 0x%04x\n";
25
26int main_child()
27{
28#ifdef WORKAROUND
29 atexit(child_exit);
30#endif
31
32 printf(child_str, getpid());
33
34 return 0x11;
35}
36
37int 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
170int main(int argc, const char** argv)
171{
172 if (argc > 1)
173 return main_child();
174 return main_parent(argc, argv);
175}