@@ -125,9 +125,13 @@ cc -I/usr/local/include -o example_ev example_ev.c -Wl,-rpath /usr/local/lib -lc
125125#include <ares.h>
126126
127127typedef struct {
128- ares_channel_t * channel;
129- struct pollfd * fds;
130- size_t nfds;
128+ ares_channel_t * channel;
129+ struct pollfd * poll_fds;
130+ size_t poll_nfds;
131+ size_t poll_fds_alloc;
132+
133+ ares_fd_events_t * ares_fds;
134+ size_t ares_nfds;
131135} dnsstate_t;
132136
133137void sock_state_cb(void * data, ares_socket_t socket_fd, int readable, int writable)
@@ -136,40 +140,49 @@ void sock_state_cb(void *data, ares_socket_t socket_fd, int readable, int writab
136140 size_t idx;
137141
138142 /* Find match * /
139- for (idx=0; idx<state- >nfds ; idx++) {
140- if (state->fds [ idx] .fd == socket_fd) {
143+ for (idx=0; idx<state- >poll_nfds ; idx++) {
144+ if (state->poll_fds [ idx] .fd == socket_fd) {
141145 break;
142146 }
143147 }
144148
145149 /* Not found * /
146- if (idx >= state->nfds ) {
150+ if (idx >= state->poll_nfds ) {
147151 /* Do nothing * /
148152 if (!readable && !writable) {
149153 return;
150154 }
151155
152156 /* Add */
153- state->nfds++;
154- state->fds = realloc(state->fds, sizeof(*state->fds) * state->nfds);
157+ state->poll_nfds++;
158+ if (state->poll_nfds > state->poll_fds_alloc) {
159+ state->poll_fds_alloc = state->poll_nfds;
160+
161+ state->poll_fds = realloc(state->poll_fds,
162+ sizeof(*state->poll_fds) * state->poll_nfds);
163+
164+ /* Make the ares_fds the same size */
165+ state->ares_fds = realloc(state->ares_fds,
166+ sizeof(*state->ares_fds) * state->poll_nfds);
167+ }
155168 } else {
156169 /* Remove * /
157170 if (!readable && !writable) {
158- memmove(&state->fds [ idx] , &state->fds [ idx+1] ,
159- sizeof(* state->fds ) * (state->nfds - idx - 1));
160- state->nfds --;
171+ memmove(&state->poll_fds [ idx] , &state->poll_fds [ idx+1] ,
172+ sizeof(* state->poll_fds ) * (state->poll_nfds - idx - 1));
173+ state->poll_nfds --;
161174 return;
162175 }
163176 }
164177
165178 /* Update Poll Events (including on Add) * /
166- state->fds [ idx] .fd = socket_fd;
167- state->fds [ idx] .events = 0;
179+ state->poll_fds [ idx] .fd = socket_fd;
180+ state->poll_fds [ idx] .events = 0;
168181 if (readable) {
169- state->fds [ idx] .events |= POLLIN;
182+ state->poll_fds [ idx] .events |= POLLIN;
170183 }
171184 if (writable) {
172- state->fds [ idx] .events |= POLLOUT;
185+ state->poll_fds [ idx] .events |= POLLOUT;
173186 }
174187}
175188
@@ -181,8 +194,6 @@ void process(dnsstate_t *state)
181194 int rv;
182195 int timeout;
183196 size_t i;
184- struct pollfd * fds;
185- size_t nfds;
186197
187198 /* Since we don't have any other program state to wait on, we'll just
188199 * stop looping when we know there are no remaining queries, which is
@@ -193,7 +204,7 @@ void process(dnsstate_t *state)
193204
194205 timeout = tv.tv_sec * 1000 + tv.tv_usec / 1000;
195206
196- rv = poll(state->fds , state->nfds , timeout);
207+ rv = poll(state->poll_fds , state->poll_nfds , timeout);
197208 if (rv < 0) {
198209 continue;
199210 } else if (rv == 0) {
@@ -202,24 +213,29 @@ void process(dnsstate_t *state)
202213 continue;
203214 }
204215
205- /* Duplicate fds structure as calling into ares_process_fd() may manipulate
206- * the one contained in state */
207- nfds = state->nfds;
208- fds = malloc(sizeof(*fds) * nfds);
209- memcpy(fds, state->fds, sizeof(*fds) * nfds);
210-
211- for (i=0; i<nfds; i++) {
212- if (fds[i].revents == 0) {
216+ /* Form our notification array */
217+ state->ares_nfds = 0;
218+ for (i=0; i<state->poll_nfds; i++) {
219+ size_t idx;
220+ if (state->poll_fds[i].revents == 0) {
213221 continue;
214222 }
215223
216- /* Notify about read/write events per FD */
217- ares_process_fd(state->channel,
218- (fds[i].revents & (POLLERR|POLLHUP|POLLIN))?fds[i].fd:ARES_SOCKET_BAD,
219- (fds[i].revents & POLLOUT)?fds[i].fd:ARES_SOCKET_BAD);
224+ idx = state->ares_nfds++;
225+
226+ state->ares_fds[idx].fd = state->poll_fds[i].fd;
227+ state->ares_fds[idx].events = 0;
228+ if (state->poll_fds[i].revents & (POLLERR|POLLHUP|POLLIN)) {
229+ state->ares_fds[idx].events |= ARES_FD_EVENT_READ;
230+ }
231+ if (state->poll_fds[i].revents & POLLOUT) {
232+ state->ares_fds[idx].events |= ARES_FD_EVENT_WRITE;
233+ }
220234 }
221235
222- free(fds);
236+ /* Notify about read/write events per FD */
237+ ares_process_fds(state->channel, state->ares_fds, state->ares_nfds,
238+ ARES_PROCESS_FLAG_NONE);
223239 }
224240}
225241
@@ -296,7 +312,8 @@ int main(int argc, char **argv)
296312
297313 /* Cleanup * /
298314 ares_destroy(state.channel);
299- free(state.fds);
315+ free(state.poll_fds);
316+ free(state.ares_fds);
300317
301318 ares_library_cleanup();
302319 return 0;
0 commit comments