]> git.ipfire.org Git - ipfire-2.x.git/blob - src/patches/dnsmasq/0058-Fix-boilerplate-code-for-re-running-system-calls-on-.patch
Core90: Update crontab.
[ipfire-2.x.git] / src / patches / dnsmasq / 0058-Fix-boilerplate-code-for-re-running-system-calls-on-.patch
1 From ff841ebf5a5d6864ff48571f607c32ce80dbb75a Mon Sep 17 00:00:00 2001
2 From: Simon Kelley <simon@thekelleys.org.uk>
3 Date: Wed, 11 Mar 2015 21:36:30 +0000
4 Subject: [PATCH 58/71] Fix boilerplate code for re-running system calls on
5 EINTR and EAGAIN etc.
6
7 The nasty code with static variable in retry_send() which
8 avoids looping forever needs to be called on success of the syscall,
9 to reset the static variable.
10 ---
11 src/bpf.c | 2 +-
12 src/dhcp.c | 2 +-
13 src/dhcp6.c | 6 +++---
14 src/dnsmasq.c | 35 +++++++++++++++++----------------
15 src/dnsmasq.h | 2 +-
16 src/forward.c | 41 ++++++++++++++++++--------------------
17 src/ipset.c | 8 ++++----
18 src/loop.c | 5 +++--
19 src/netlink.c | 8 ++++----
20 src/radv.c | 5 +++--
21 src/util.c | 63 ++++++++++++++++++++++++++++++++++-------------------------
22 11 files changed, 93 insertions(+), 84 deletions(-)
23
24 diff --git a/src/bpf.c b/src/bpf.c
25 index 997d87421bed..a066641f969f 100644
26 --- a/src/bpf.c
27 +++ b/src/bpf.c
28 @@ -359,7 +359,7 @@ void send_via_bpf(struct dhcp_packet *mess, size_t len,
29 iov[3].iov_base = mess;
30 iov[3].iov_len = len;
31
32 - while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
33 + while (retry_send(writev(daemon->dhcp_raw_fd, iov, 4)));
34 }
35
36 #endif /* defined(HAVE_BSD_NETWORK) && defined(HAVE_DHCP) */
37 diff --git a/src/dhcp.c b/src/dhcp.c
38 index f29be9b489a7..5c3089ab94ff 100644
39 --- a/src/dhcp.c
40 +++ b/src/dhcp.c
41 @@ -443,7 +443,7 @@ void dhcp_packet(time_t now, int pxe_fd)
42 setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
43 #endif
44
45 - while(sendmsg(fd, &msg, 0) == -1 && retry_send());
46 + while(retry_send(sendmsg(fd, &msg, 0)));
47 }
48
49 /* check against secondary interface addresses */
50 diff --git a/src/dhcp6.c b/src/dhcp6.c
51 index c7144f5fee7c..ee2aa5d3bf3c 100644
52 --- a/src/dhcp6.c
53 +++ b/src/dhcp6.c
54 @@ -225,9 +225,9 @@ void dhcp6_packet(time_t now)
55 if (port != 0)
56 {
57 from.sin6_port = htons(port);
58 - while (sendto(daemon->dhcp6fd, daemon->outpacket.iov_base, save_counter(0),
59 - 0, (struct sockaddr *)&from, sizeof(from)) == -1 &&
60 - retry_send());
61 + while (retry_send(sendto(daemon->dhcp6fd, daemon->outpacket.iov_base,
62 + save_counter(0), 0, (struct sockaddr *)&from,
63 + sizeof(from))));
64 }
65 }
66
67 diff --git a/src/dnsmasq.c b/src/dnsmasq.c
68 index f3e5bcffec4f..b784951950d4 100644
69 --- a/src/dnsmasq.c
70 +++ b/src/dnsmasq.c
71 @@ -444,7 +444,7 @@ int main (int argc, char **argv)
72 char *msg;
73
74 /* close our copy of write-end */
75 - close(err_pipe[1]);
76 + while (retry_send(close(err_pipe[1])));
77
78 /* check for errors after the fork */
79 if (read_event(err_pipe[0], &ev, &msg))
80 @@ -453,7 +453,7 @@ int main (int argc, char **argv)
81 _exit(EC_GOOD);
82 }
83
84 - close(err_pipe[0]);
85 + while (retry_send(close(err_pipe[0])));
86
87 /* NO calls to die() from here on. */
88
89 @@ -505,10 +505,12 @@ int main (int argc, char **argv)
90 {
91 if (!read_write(fd, (unsigned char *)daemon->namebuff, strlen(daemon->namebuff), 0))
92 err = 1;
93 -
94 - while (!err && close(fd) == -1)
95 - if (!retry_send())
96 - err = 1;
97 + else
98 + {
99 + while (retry_send(close(fd)));
100 + if (errno != 0)
101 + err = 1;
102 + }
103 }
104
105 if (err)
106 @@ -813,7 +815,7 @@ int main (int argc, char **argv)
107
108 /* finished start-up - release original process */
109 if (err_pipe[1] != -1)
110 - close(err_pipe[1]);
111 + while (retry_send(close(err_pipe[1])));
112
113 if (daemon->port != 0)
114 check_servers();
115 @@ -1319,7 +1321,7 @@ static void async_event(int pipe, time_t now)
116 do {
117 helper_write();
118 } while (!helper_buf_empty() || do_script_run(now));
119 - close(daemon->helperfd);
120 + while (retry_send(close(daemon->helperfd)));
121 }
122 #endif
123
124 @@ -1544,7 +1546,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
125
126 if (getsockname(confd, (struct sockaddr *)&tcp_addr, &tcp_len) == -1)
127 {
128 - close(confd);
129 + while (retry_send(close(confd)));
130 continue;
131 }
132
133 @@ -1609,7 +1611,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
134 if (!client_ok)
135 {
136 shutdown(confd, SHUT_RDWR);
137 - close(confd);
138 + while (retry_send(close(confd)));
139 }
140 #ifndef NO_FORK
141 else if (!option_bool(OPT_DEBUG) && (p = fork()) != 0)
142 @@ -1624,7 +1626,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
143 break;
144 }
145 }
146 - close(confd);
147 + while (retry_send(close(confd)));
148
149 /* The child can use up to TCP_MAX_QUERIES ids, so skip that many. */
150 daemon->log_id += TCP_MAX_QUERIES;
151 @@ -1669,7 +1671,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
152 buff = tcp_request(confd, now, &tcp_addr, netmask, auth_dns);
153
154 shutdown(confd, SHUT_RDWR);
155 - close(confd);
156 + while (retry_send(close(confd)));
157
158 if (buff)
159 free(buff);
160 @@ -1678,7 +1680,7 @@ static void check_dns_listeners(fd_set *set, time_t now)
161 if (s->tcpfd != -1)
162 {
163 shutdown(s->tcpfd, SHUT_RDWR);
164 - close(s->tcpfd);
165 + while (retry_send(close(s->tcpfd)));
166 }
167 #ifndef NO_FORK
168 if (!option_bool(OPT_DEBUG))
169 @@ -1756,9 +1758,8 @@ int icmp_ping(struct in_addr addr)
170 j = (j & 0xffff) + (j >> 16);
171 packet.icmp.icmp_cksum = (j == 0xffff) ? j : ~j;
172
173 - while (sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
174 - (struct sockaddr *)&saddr, sizeof(saddr)) == -1 &&
175 - retry_send());
176 + while (retry_send(sendto(fd, (char *)&packet.icmp, sizeof(struct icmp), 0,
177 + (struct sockaddr *)&saddr, sizeof(saddr))));
178
179 for (now = start = dnsmasq_time();
180 difftime(now, start) < (float)PING_WAIT;)
181 @@ -1820,7 +1821,7 @@ int icmp_ping(struct in_addr addr)
182 }
183
184 #if defined(HAVE_LINUX_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
185 - close(fd);
186 + while (retry_send(close(fd)));
187 #else
188 opt = 1;
189 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
190 diff --git a/src/dnsmasq.h b/src/dnsmasq.h
191 index fc7259881358..de95d0e875e3 100644
192 --- a/src/dnsmasq.h
193 +++ b/src/dnsmasq.h
194 @@ -1177,7 +1177,7 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen);
195 u64 addr6part(struct in6_addr *addr);
196 void setaddr6part(struct in6_addr *addr, u64 host);
197 #endif
198 -int retry_send(void);
199 +int retry_send(ssize_t rc);
200 void prettyprint_time(char *buf, unsigned int t);
201 int prettyprint_addr(union mysockaddr *addr, char *buf);
202 int parse_hex(char *in, unsigned char *out, int maxlen,
203 diff --git a/src/forward.c b/src/forward.c
204 index 438e9fa490b8..7c0fa8da3fdf 100644
205 --- a/src/forward.c
206 +++ b/src/forward.c
207 @@ -103,15 +103,11 @@ int send_from(int fd, int nowild, char *packet, size_t len,
208 #endif
209 }
210
211 - while (sendmsg(fd, &msg, 0) == -1)
212 + while (retry_send(sendmsg(fd, &msg, 0)));
213 +
214 + /* If interface is still in DAD, EINVAL results - ignore that. */
215 + if (errno != 0 && errno != EINVAL)
216 {
217 - if (retry_send())
218 - continue;
219 -
220 - /* If interface is still in DAD, EINVAL results - ignore that. */
221 - if (errno == EINVAL)
222 - break;
223 -
224 my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
225 return 0;
226 }
227 @@ -297,9 +293,9 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
228 fd = forward->rfd4->fd;
229 }
230
231 - while (sendto(fd, (char *)header, plen, 0,
232 - &forward->sentto->addr.sa,
233 - sa_len(&forward->sentto->addr)) == -1 && retry_send());
234 + while (retry_send( sendto(fd, (char *)header, plen, 0,
235 + &forward->sentto->addr.sa,
236 + sa_len(&forward->sentto->addr))));
237
238 return 1;
239 }
240 @@ -469,14 +465,12 @@ static int forward_query(int udpfd, union mysockaddr *udpaddr,
241 #endif
242 }
243
244 - if (sendto(fd, (char *)header, plen, 0,
245 - &start->addr.sa,
246 - sa_len(&start->addr)) == -1)
247 - {
248 - if (retry_send())
249 - continue;
250 - }
251 - else
252 + if (retry_send(sendto(fd, (char *)header, plen, 0,
253 + &start->addr.sa,
254 + sa_len(&start->addr))))
255 + continue;
256 +
257 + if (errno == 0)
258 {
259 /* Keep info in case we want to re-send this packet */
260 daemon->srv_save = start;
261 @@ -932,7 +926,9 @@ void reply_query(int fd, int family, time_t now)
262
263 if (fd != -1)
264 {
265 - while (sendto(fd, (char *)header, nn, 0, &server->addr.sa, sa_len(&server->addr)) == -1 && retry_send());
266 + while (retry_send(sendto(fd, (char *)header, nn, 0,
267 + &server->addr.sa,
268 + sa_len(&server->addr))));
269 server->queries++;
270 }
271
272 @@ -2228,8 +2224,9 @@ void resend_query()
273 else
274 return;
275
276 - while(sendto(fd, daemon->packet, daemon->packet_len, 0,
277 - &daemon->srv_save->addr.sa, sa_len(&daemon->srv_save->addr)) == -1 && retry_send());
278 + while(retry_send(sendto(fd, daemon->packet, daemon->packet_len, 0,
279 + &daemon->srv_save->addr.sa,
280 + sa_len(&daemon->srv_save->addr))));
281 }
282 }
283
284 diff --git a/src/ipset.c b/src/ipset.c
285 index 8c5b72722371..a315e86bc7f4 100644
286 --- a/src/ipset.c
287 +++ b/src/ipset.c
288 @@ -121,7 +121,6 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
289 struct my_nlattr *nested[2];
290 uint8_t proto;
291 int addrsz = INADDRSZ;
292 - ssize_t rc;
293
294 #ifdef HAVE_IPV6
295 if (af == AF_INET6)
296 @@ -162,9 +161,10 @@ static int new_add_to_ipset(const char *setname, const struct all_addr *ipaddr,
297 nested[1]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[1];
298 nested[0]->nla_len = (void *)buffer + NL_ALIGN(nlh->nlmsg_len) - (void *)nested[0];
299
300 - while ((rc = sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
301 - (struct sockaddr *)&snl, sizeof(snl))) == -1 && retry_send());
302 - return rc;
303 + while (retry_send(sendto(ipset_sock, buffer, nlh->nlmsg_len, 0,
304 + (struct sockaddr *)&snl, sizeof(snl))));
305 +
306 + return errno == 0 ? 0 : -1;
307 }
308
309
310 diff --git a/src/loop.c b/src/loop.c
311 index 565f7d8e58e0..c9ed075670de 100644
312 --- a/src/loop.c
313 +++ b/src/loop.c
314 @@ -45,8 +45,9 @@ void loop_send_probes()
315 fd = rfd->fd;
316 }
317
318 - while (sendto(fd, daemon->packet, len, 0, &serv->addr.sa, sa_len(&serv->addr)) == -1 && retry_send());
319 -
320 + while (retry_send(sendto(fd, daemon->packet, len, 0,
321 + &serv->addr.sa, sa_len(&serv->addr))));
322 +
323 free_rfd(rfd);
324 }
325 }
326 diff --git a/src/netlink.c b/src/netlink.c
327 index 10f94db25a14..753784dc20b4 100644
328 --- a/src/netlink.c
329 +++ b/src/netlink.c
330 @@ -169,10 +169,10 @@ int iface_enumerate(int family, void *parm, int (*callback)())
331 req.g.rtgen_family = family;
332
333 /* Don't block in recvfrom if send fails */
334 - while((len = sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
335 - (struct sockaddr *)&addr, sizeof(addr))) == -1 && retry_send());
336 -
337 - if (len == -1)
338 + while(retry_send(sendto(daemon->netlinkfd, (void *)&req, sizeof(req), 0,
339 + (struct sockaddr *)&addr, sizeof(addr))));
340 +
341 + if (errno != 0)
342 return 0;
343
344 while (1)
345 diff --git a/src/radv.c b/src/radv.c
346 index 6da125b864ae..d0faddf8684a 100644
347 --- a/src/radv.c
348 +++ b/src/radv.c
349 @@ -479,8 +479,9 @@ static void send_ra(time_t now, int iface, char *iface_name, struct in6_addr *de
350 setsockopt(daemon->icmp6fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &iface, sizeof(iface));
351 }
352
353 - while (sendto(daemon->icmp6fd, daemon->outpacket.iov_base, save_counter(0), 0,
354 - (struct sockaddr *)&addr, sizeof(addr)) == -1 && retry_send());
355 + while (retry_send(sendto(daemon->icmp6fd, daemon->outpacket.iov_base,
356 + save_counter(0), 0, (struct sockaddr *)&addr,
357 + sizeof(addr))));
358
359 }
360
361 diff --git a/src/util.c b/src/util.c
362 index 91d02410b13f..648bc4d4b428 100644
363 --- a/src/util.c
364 +++ b/src/util.c
365 @@ -569,17 +569,27 @@ void bump_maxfd(int fd, int *max)
366 *max = fd;
367 }
368
369 -int retry_send(void)
370 +/* rc is return from sendto and friends.
371 + Return 1 if we should retry.
372 + Set errno to zero if we succeeded. */
373 +int retry_send(ssize_t rc)
374 {
375 + static int retries = 0;
376 + struct timespec waiter;
377 +
378 + if (rc != -1)
379 + {
380 + retries = 0;
381 + errno = 0;
382 + return 0;
383 + }
384 +
385 /* Linux kernels can return EAGAIN in perpetuity when calling
386 sendmsg() and the relevant interface has gone. Here we loop
387 retrying in EAGAIN for 1 second max, to avoid this hanging
388 dnsmasq. */
389
390 - static int retries = 0;
391 - struct timespec waiter;
392 -
393 - if (errno == EAGAIN || errno == EWOULDBLOCK)
394 + if (errno == EAGAIN || errno == EWOULDBLOCK)
395 {
396 waiter.tv_sec = 0;
397 waiter.tv_nsec = 10000;
398 @@ -587,13 +597,13 @@ int retry_send(void)
399 if (retries++ < 1000)
400 return 1;
401 }
402 -
403 - retries = 0;
404 -
405 - if (errno == EINTR)
406 - return 1;
407 -
408 - return 0;
409 +
410 + retries = 0;
411 +
412 + if (errno == EINTR)
413 + return 1;
414 +
415 + return 0;
416 }
417
418 int read_write(int fd, unsigned char *packet, int size, int rw)
419 @@ -602,22 +612,21 @@ int read_write(int fd, unsigned char *packet, int size, int rw)
420
421 for (done = 0; done < size; done += n)
422 {
423 - retry:
424 - if (rw)
425 - n = read(fd, &packet[done], (size_t)(size - done));
426 - else
427 - n = write(fd, &packet[done], (size_t)(size - done));
428 -
429 - if (n == 0)
430 - return 0;
431 - else if (n == -1)
432 - {
433 - if (retry_send() || errno == ENOMEM || errno == ENOBUFS)
434 - goto retry;
435 - else
436 - return 0;
437 - }
438 + do {
439 + if (rw)
440 + n = read(fd, &packet[done], (size_t)(size - done));
441 + else
442 + n = write(fd, &packet[done], (size_t)(size - done));
443 +
444 + if (n == 0)
445 + return 0;
446 +
447 + } while (retry_send(n) || errno == ENOMEM || errno == ENOBUFS);
448 +
449 + if (errno != 0)
450 + return 0;
451 }
452 +
453 return 1;
454 }
455
456 --
457 2.1.0
458