]> git.saurik.com Git - apple/launchd.git/blame - launchd/testing/missed-EVFILT_WRITE.c
launchd-106.tar.gz
[apple/launchd.git] / launchd / testing / missed-EVFILT_WRITE.c
CommitLineData
e91b9f68
A
1/*
2 * <rdar://problem/4038866> Lots of hangs in GetLaunchDaemonService state
3 */
4
5#include <sys/types.h>
6#include <sys/time.h>
7#include <sys/event.h>
8#include <sys/socket.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <unistd.h>
12#include <fcntl.h>
13#include <string.h>
14#include <errno.h>
15
16static void do_parent(int thefd);
17static void do_child(int thefd);
18
19int main(void)
20{
21 int sp[2];
22
23 if (-1 == socketpair(AF_UNIX, SOCK_STREAM, 0, sp)) {
24 fprintf(stderr, "socketpair(): %s\n", strerror(errno));
25 exit(EXIT_FAILURE);
26 }
27
28 switch (fork()) {
29 case -1:
30 fprintf(stderr, "fork(): %s\n", strerror(errno));
31 exit(EXIT_FAILURE);
32 case 0:
33 close(sp[0]);
34 do_child(sp[1]);
35 break;
36 default:
37 close(sp[1]);
38 do_parent(sp[0]);
39 break;
40 }
41
42 exit(EXIT_SUCCESS);
43}
44
45static void do_child(int thefd)
46{
47 char buf[500000];
48 fd_set rfds;
49 int r, readhunks = 2;
50
51 if (-1 == fcntl(thefd, F_SETFL, O_NONBLOCK)) {
52 fprintf(stderr, "fcntl(): %s\n", strerror(errno));
53 exit(EXIT_FAILURE);
54 }
55
56 for (;;) {
57 if (2 == readhunks) {
58 if (-1 == write(thefd, buf, 1)) {
59 fprintf(stderr, "%d: write(): %s\n", __LINE__, strerror(errno));
60 exit(EXIT_FAILURE);
61 }
62 readhunks = 0;
63 }
64 r = read(thefd, buf, sizeof(buf));
65
66 if (-1 == r && errno != EAGAIN) {
67 fprintf(stderr, "%d: read(): %s\n", __LINE__, strerror(errno));
68 exit(EXIT_FAILURE);
69 }
70
71 if (r > 0)
72 readhunks++;
73
74 if (readhunks == 2)
75 continue;
76
77 FD_ZERO(&rfds);
78 FD_SET(thefd, &rfds);
79
80 select(thefd + 1, &rfds, NULL, NULL, NULL);
81 }
82}
83
84static void do_parent(int thefd)
85{
86 struct timespec timeout = { 1, 0 };
87 char buf[500000];
88 struct kevent kev;
89 int iter = 0, kq = kqueue();
90
91 if (-1 == (kq = kqueue())) {
92 fprintf(stderr, "kqueue(): %s\n", strerror(errno));
93 exit(EXIT_FAILURE);
94 }
95
96 if (-1 == fcntl(thefd, F_SETFL, O_NONBLOCK)) {
97 fprintf(stderr, "fcntl(): %s\n", strerror(errno));
98 exit(EXIT_FAILURE);
99 }
100
101 EV_SET(&kev, thefd, EVFILT_READ, EV_ADD, 0, 0, NULL);
102
103 if (-1 == kevent(kq, &kev, 1, NULL, 0, NULL)) {
104 fprintf(stderr, "%d: kevent(): %s\n", __LINE__, strerror(errno));
105 exit(EXIT_FAILURE);
106 }
107
108 for (;;) {
109 switch (kevent(kq, NULL, 0, &kev, 1, &timeout)) {
110 case -1:
111 fprintf(stderr, "%d: kevent(): %s\n", __LINE__, strerror(errno));
112 exit(EXIT_FAILURE);
113 case 0:
114 fprintf(stderr, "After %d iterations, 4038866 still exists!\n", iter);
115 exit(EXIT_FAILURE);
116 case 1:
117 break;
118 default:
119 fprintf(stderr, "kevent should only return -1, 0 or 1 for this case!\n");
120 exit(EXIT_FAILURE);
121 }
122
123 switch (kev.filter) {
124 case EVFILT_READ:
125 if (-1 == read(thefd, buf, sizeof(buf))) {
126 fprintf(stderr, "read(): %s\n", strerror(errno));
127 exit(EXIT_FAILURE);
128 }
129 if (-1 == write(thefd, buf, sizeof(buf))) {
130 fprintf(stderr, "%d: write(): %s\n", __LINE__, strerror(errno));
131 exit(EXIT_FAILURE);
132 }
133 EV_SET(&kev, thefd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
134 if (-1 == kevent(kq, &kev, 1, NULL, 0, NULL)) {
135 fprintf(stderr, "%d: kevent(): %s\n", __LINE__, strerror(errno));
136 exit(EXIT_FAILURE);
137 }
138 break;
139 case EVFILT_WRITE:
140 if (-1 == write(thefd, buf, 1)) {
141 fprintf(stderr, "%d: write(): %s\n", __LINE__, strerror(errno));
142 exit(EXIT_FAILURE);
143 }
144 EV_SET(&kev, thefd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL);
145 if (-1 == kevent(kq, &kev, 1, NULL, 0, NULL)) {
146 fprintf(stderr, "%d: kevent(): %s\n", __LINE__, strerror(errno));
147 exit(EXIT_FAILURE);
148 }
149 break;
150 default:
151 fprintf(stderr, "kevent filter isn't EVFILT_READ or EVFILT_WRITE!\n");
152 exit(EXIT_FAILURE);
153 }
154 iter++;
155 }
156}