Removed
Link Here
|
1 |
--- util/netevent.c.orig 2023-08-30 01:01:13.000000000 -0700 |
2 |
+++ util/netevent.c 2023-10-12 19:00:53.157995000 -0700 |
3 |
@@ -116,6 +116,8 @@ |
4 |
|
5 |
/** timeout in millisec to wait for write to unblock, packets dropped after.*/ |
6 |
#define SEND_BLOCKED_WAIT_TIMEOUT 200 |
7 |
+/** max number of times to wait for write to unblock, packets dropped after.*/ |
8 |
+#define SEND_BLOCKED_MAX_RETRY 5 |
9 |
|
10 |
/** Let's make timestamping code cleaner and redefine SO_TIMESTAMP* */ |
11 |
#ifndef SO_TIMESTAMP |
12 |
@@ -402,9 +404,10 @@ |
13 |
WSAGetLastError() == WSAENOBUFS || |
14 |
WSAGetLastError() == WSAEWOULDBLOCK) { |
15 |
#endif |
16 |
+ int retries = 0; |
17 |
/* if we set the fd blocking, other threads suddenly |
18 |
* have a blocking fd that they operate on */ |
19 |
- while(sent == -1 && ( |
20 |
+ while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && ( |
21 |
#ifndef USE_WINSOCK |
22 |
errno == EAGAIN || errno == EINTR || |
23 |
# ifdef EWOULDBLOCK |
24 |
@@ -419,6 +422,13 @@ |
25 |
#endif |
26 |
)) { |
27 |
#if defined(HAVE_POLL) || defined(USE_WINSOCK) |
28 |
+ int send_nobufs = ( |
29 |
+#ifndef USE_WINSOCK |
30 |
+ errno == ENOBUFS |
31 |
+#else |
32 |
+ WSAGetLastError() == WSAENOBUFS |
33 |
+#endif |
34 |
+ ); |
35 |
struct pollfd p; |
36 |
int pret; |
37 |
memset(&p, 0, sizeof(p)); |
38 |
@@ -457,8 +467,48 @@ |
39 |
log_err("poll udp out failed: %s", |
40 |
sock_strerror(errno)); |
41 |
return 0; |
42 |
+ } else if((pret < 0 && |
43 |
+#ifndef USE_WINSOCK |
44 |
+ errno == ENOBUFS |
45 |
+#else |
46 |
+ WSAGetLastError() == WSAENOBUFS |
47 |
+#endif |
48 |
+ ) || (send_nobufs && retries > 0)) { |
49 |
+ /* ENOBUFS, and poll returned without |
50 |
+ * a timeout. Or the retried send call |
51 |
+ * returned ENOBUFS. It is good to |
52 |
+ * wait a bit for the error to clear. */ |
53 |
+ /* The timeout is 20*(2^(retries+1)), |
54 |
+ * it increases exponentially, starting |
55 |
+ * at 40 msec. After 5 tries, 1240 msec |
56 |
+ * have passed in total, when poll |
57 |
+ * returned the error, and 1200 msec |
58 |
+ * when send returned the errors. */ |
59 |
+#ifndef USE_WINSOCK |
60 |
+ pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); |
61 |
+#else |
62 |
+ pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); |
63 |
+#endif |
64 |
+ if(pret < 0 && |
65 |
+#ifndef USE_WINSOCK |
66 |
+ errno != EAGAIN && errno != EINTR && |
67 |
+# ifdef EWOULDBLOCK |
68 |
+ errno != EWOULDBLOCK && |
69 |
+# endif |
70 |
+ errno != ENOBUFS |
71 |
+#else |
72 |
+ WSAGetLastError() != WSAEINPROGRESS && |
73 |
+ WSAGetLastError() != WSAEINTR && |
74 |
+ WSAGetLastError() != WSAENOBUFS && |
75 |
+ WSAGetLastError() != WSAEWOULDBLOCK |
76 |
+#endif |
77 |
+ ) { |
78 |
+ log_err("poll udp out timer failed: %s", |
79 |
+ sock_strerror(errno)); |
80 |
+ } |
81 |
} |
82 |
#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ |
83 |
+ retries++; |
84 |
if (!is_connected) { |
85 |
sent = sendto(c->fd, (void*)sldns_buffer_begin(packet), |
86 |
sldns_buffer_remaining(packet), 0, |
87 |
@@ -665,7 +715,8 @@ |
88 |
WSAGetLastError() == WSAENOBUFS || |
89 |
WSAGetLastError() == WSAEWOULDBLOCK) { |
90 |
#endif |
91 |
- while(sent == -1 && ( |
92 |
+ int retries = 0; |
93 |
+ while(sent == -1 && retries < SEND_BLOCKED_MAX_RETRY && ( |
94 |
#ifndef USE_WINSOCK |
95 |
errno == EAGAIN || errno == EINTR || |
96 |
# ifdef EWOULDBLOCK |
97 |
@@ -680,6 +731,13 @@ |
98 |
#endif |
99 |
)) { |
100 |
#if defined(HAVE_POLL) || defined(USE_WINSOCK) |
101 |
+ int send_nobufs = ( |
102 |
+#ifndef USE_WINSOCK |
103 |
+ errno == ENOBUFS |
104 |
+#else |
105 |
+ WSAGetLastError() == WSAENOBUFS |
106 |
+#endif |
107 |
+ ); |
108 |
struct pollfd p; |
109 |
int pret; |
110 |
memset(&p, 0, sizeof(p)); |
111 |
@@ -718,8 +776,48 @@ |
112 |
log_err("poll udp out failed: %s", |
113 |
sock_strerror(errno)); |
114 |
return 0; |
115 |
+ } else if((pret < 0 && |
116 |
+#ifndef USE_WINSOCK |
117 |
+ errno == ENOBUFS |
118 |
+#else |
119 |
+ WSAGetLastError() == WSAENOBUFS |
120 |
+#endif |
121 |
+ ) || (send_nobufs && retries > 0)) { |
122 |
+ /* ENOBUFS, and poll returned without |
123 |
+ * a timeout. Or the retried send call |
124 |
+ * returned ENOBUFS. It is good to |
125 |
+ * wait a bit for the error to clear. */ |
126 |
+ /* The timeout is 20*(2^(retries+1)), |
127 |
+ * it increases exponentially, starting |
128 |
+ * at 40 msec. After 5 tries, 1240 msec |
129 |
+ * have passed in total, when poll |
130 |
+ * returned the error, and 1200 msec |
131 |
+ * when send returned the errors. */ |
132 |
+#ifndef USE_WINSOCK |
133 |
+ pret = poll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); |
134 |
+#else |
135 |
+ pret = WSAPoll(NULL, 0, (SEND_BLOCKED_WAIT_TIMEOUT/10)<<(retries+1)); |
136 |
+#endif |
137 |
+ if(pret < 0 && |
138 |
+#ifndef USE_WINSOCK |
139 |
+ errno != EAGAIN && errno != EINTR && |
140 |
+# ifdef EWOULDBLOCK |
141 |
+ errno != EWOULDBLOCK && |
142 |
+# endif |
143 |
+ errno != ENOBUFS |
144 |
+#else |
145 |
+ WSAGetLastError() != WSAEINPROGRESS && |
146 |
+ WSAGetLastError() != WSAEINTR && |
147 |
+ WSAGetLastError() != WSAENOBUFS && |
148 |
+ WSAGetLastError() != WSAEWOULDBLOCK |
149 |
+#endif |
150 |
+ ) { |
151 |
+ log_err("poll udp out timer failed: %s", |
152 |
+ sock_strerror(errno)); |
153 |
+ } |
154 |
} |
155 |
#endif /* defined(HAVE_POLL) || defined(USE_WINSOCK) */ |
156 |
+ retries++; |
157 |
sent = sendmsg(c->fd, &msg, 0); |
158 |
} |
159 |
} |