Added
Link Here
|
0 |
- |
1 |
From 490cb06ef878bff1e45acf313105205df7baced1 Mon Sep 17 00:00:00 2001 |
|
|
2 |
From: Eygene Ryabinkin <rea-fbsd@codelabs.ru> |
3 |
Date: Sun, 21 Dec 2008 15:18:11 +0300 |
4 |
Subject: [PATCH] Add processing of both READ and WRITE events inside libevent handlers |
5 |
|
6 |
If both read and write descriptors are ready, then libevent will set |
7 |
both EV_READ and EV_WRITE. Original OpenOSPFD sources were not ready to |
8 |
handle such situations, but OpenBSD's libevent (1.3e with some local |
9 |
tweaks) and even libevent 1.0 can also produce combined read/write |
10 |
events (if manual page is correct ;). |
11 |
|
12 |
Such errors were seen in the wild, for example Remko Lodder had been |
13 |
biten by this issue. |
14 |
|
15 |
I had created inline function that will be called from both 6 places |
16 |
that are handling READ/WRITE events to eliminate code duplication. |
17 |
|
18 |
Signed-off-by: Eygene Ryabinkin <rea-fbsd@codelabs.ru> |
19 |
--- |
20 |
ospfd/libevent_helpers.h | 81 ++++++++++++++++++++++++++++++++++++++++++++++ |
21 |
ospfd/ospfd.c | 31 ++---------------- |
22 |
ospfd/ospfe.c | 39 ++++----------------- |
23 |
ospfd/rde.c | 31 ++---------------- |
24 |
4 files changed, 95 insertions(+), 87 deletions(-) |
25 |
create mode 100644 ospfd/libevent_helpers.h |
26 |
|
27 |
diff --git a/ospfd/libevent_helpers.h b/ospfd/libevent_helpers.h |
28 |
new file mode 100644 |
29 |
index 0000000..46f743d |
30 |
--- /dev/null |
31 |
+++ ospfd/libevent_helpers.h |
32 |
@@ -0,0 +1,81 @@ |
33 |
+/* |
34 |
+ * Copyright (c) 2008 Eygene Ryabinkin <rea-fbsd@codelabs.ru> |
35 |
+ * |
36 |
+ * Permission to use, copy, modify, and distribute this software for any |
37 |
+ * purpose with or without fee is hereby granted, provided that the above |
38 |
+ * copyright notice and this permission notice appear in all copies. |
39 |
+ * |
40 |
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
41 |
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
42 |
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
43 |
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
44 |
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
45 |
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
46 |
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
47 |
+ */ |
48 |
+ |
49 |
+#ifndef _LIBEVENT_HELPERS_H_ |
50 |
+#define _LIBEVENT_HELPERS_H_ |
51 |
+ |
52 |
+#include <stdio.h> |
53 |
+#include <sys/types.h> |
54 |
+ |
55 |
+#include "log.h" |
56 |
+#include "ospfd.h" |
57 |
+ |
58 |
+/* Inline functions */ |
59 |
+ |
60 |
+/* |
61 |
+ * A support function that processes libevent notification in the |
62 |
+ * following way: |
63 |
+ * - if we are ready to write, we will try to flush the queue; |
64 |
+ * - if we are ready to read, we will read the input buffer and |
65 |
+ * prepare variables 'n' and 'shut' accordingly. |
66 |
+ * |
67 |
+ * Such handling occurs at least 6 times within the OSPFD sources, |
68 |
+ * so this inline function is just an alternative to the preprocessor |
69 |
+ * macros. |
70 |
+ * |
71 |
+ * Function returns 0 if everything was handled and no further |
72 |
+ * processing is needed; it returns EV_READ if the read processing |
73 |
+ * was prepared to take place. |
74 |
+ */ |
75 |
+static inline short |
76 |
+dispatch_read_write_event(short _event, struct imsgbuf *_ibuf, |
77 |
+ ssize_t *_n, int *_shut) __attribute__((always_inline)); |
78 |
+ |
79 |
+static inline short |
80 |
+dispatch_read_write_event(short event, struct imsgbuf *ibuf, |
81 |
+ ssize_t *n, int *shut) |
82 |
+{ |
83 |
+ static char errbuf[128]; |
84 |
+ |
85 |
+ /* |
86 |
+ * We can have both EV_READ and EV_WRITE, since we can be |
87 |
+ * subscribed to both event types. Handle write readiness |
88 |
+ * first (flush the queue) and then handle reads. |
89 |
+ */ |
90 |
+ if ((event & ~(EV_WRITE|EV_READ))) { |
91 |
+ snprintf(errbuf, sizeof(errbuf), |
92 |
+ "unknown event 0x%hx", (unsigned short)event); |
93 |
+ fatalx(errbuf); |
94 |
+ } |
95 |
+ |
96 |
+ if ((event & EV_WRITE)) { |
97 |
+ if (msgbuf_write(&ibuf->w) == -1) |
98 |
+ fatal("msgbuf_write"); |
99 |
+ imsg_event_add(ibuf); |
100 |
+ } |
101 |
+ if ((event & EV_READ)) { |
102 |
+ if ((*n = imsg_read(ibuf)) == -1) |
103 |
+ fatal("imsg_read error"); |
104 |
+ if (*n == 0) /* connection closed */ |
105 |
+ *shut = 1; |
106 |
+ return EV_READ; |
107 |
+ } else { |
108 |
+ return 0; |
109 |
+ } |
110 |
+ /* NOTREACHED */ |
111 |
+} |
112 |
+ |
113 |
+#endif /* _LIBEVENT_HELPERS_H_ */ |
114 |
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c |
115 |
index be69cab..4e62d09 100644 |
116 |
--- ospfd/ospfd.c |
117 |
+++ ospfd/ospfd.c |
118 |
@@ -46,6 +46,7 @@ |
119 |
#include "control.h" |
120 |
#include "log.h" |
121 |
#include "rde.h" |
122 |
+#include "libevent_helpers.h" |
123 |
|
124 |
void main_sig_handler(int, short, void *); |
125 |
__dead void usage(void); |
126 |
@@ -355,21 +356,8 @@ main_dispatch_ospfe(int fd, short event, void *bula) |
127 |
ssize_t n; |
128 |
int shut = 0; |
129 |
|
130 |
- switch (event) { |
131 |
- case EV_READ: |
132 |
- if ((n = imsg_read(ibuf)) == -1) |
133 |
- fatal("imsg_read error"); |
134 |
- if (n == 0) /* connection closed */ |
135 |
- shut = 1; |
136 |
- break; |
137 |
- case EV_WRITE: |
138 |
- if (msgbuf_write(&ibuf->w) == -1) |
139 |
- fatal("msgbuf_write"); |
140 |
- imsg_event_add(ibuf); |
141 |
+ if (dispatch_read_write_event(event, ibuf, &n, &shut) != EV_READ) |
142 |
return; |
143 |
- default: |
144 |
- fatalx("unknown event"); |
145 |
- } |
146 |
|
147 |
for (;;) { |
148 |
if ((n = imsg_get(ibuf, &imsg)) == -1) |
149 |
@@ -434,21 +422,8 @@ main_dispatch_rde(int fd, short event, void *bula) |
150 |
ssize_t n; |
151 |
int count, shut = 0; |
152 |
|
153 |
- switch (event) { |
154 |
- case EV_READ: |
155 |
- if ((n = imsg_read(ibuf)) == -1) |
156 |
- fatal("imsg_read error"); |
157 |
- if (n == 0) /* connection closed */ |
158 |
- shut = 1; |
159 |
- break; |
160 |
- case EV_WRITE: |
161 |
- if (msgbuf_write(&ibuf->w) == -1) |
162 |
- fatal("msgbuf_write"); |
163 |
- imsg_event_add(ibuf); |
164 |
+ if (dispatch_read_write_event(event, ibuf, &n, &shut) != EV_READ) |
165 |
return; |
166 |
- default: |
167 |
- fatalx("unknown event"); |
168 |
- } |
169 |
|
170 |
for (;;) { |
171 |
if ((n = imsg_get(ibuf, &imsg)) == -1) |
172 |
diff --git a/ospfd/ospfe.c b/ospfd/ospfe.c |
173 |
index af7a406..d6a6aa9 100644 |
174 |
--- ospfd/ospfe.c |
175 |
+++ ospfd/ospfe.c |
176 |
@@ -42,6 +42,7 @@ |
177 |
#include "rde.h" |
178 |
#include "control.h" |
179 |
#include "log.h" |
180 |
+#include "libevent_helpers.h" |
181 |
|
182 |
void ospfe_sig_handler(int, short, void *); |
183 |
void ospfe_shutdown(void); |
184 |
@@ -257,23 +258,11 @@ ospfe_dispatch_main(int fd, short event, void *bula) |
185 |
struct iface *iface = NULL; |
186 |
struct kif *kif; |
187 |
struct auth_md md; |
188 |
- int n, link_ok, stub_changed, shut = 0; |
189 |
- |
190 |
- switch (event) { |
191 |
- case EV_READ: |
192 |
- if ((n = imsg_read(ibuf)) == -1) |
193 |
- fatal("imsg_read error"); |
194 |
- if (n == 0) /* connection closed */ |
195 |
- shut = 1; |
196 |
- break; |
197 |
- case EV_WRITE: |
198 |
- if (msgbuf_write(&ibuf->w) == -1) |
199 |
- fatal("msgbuf_write"); |
200 |
- imsg_event_add(ibuf); |
201 |
+ int link_ok, stub_changed, shut = 0; |
202 |
+ ssize_t n; |
203 |
+ |
204 |
+ if (dispatch_read_write_event(event, ibuf, &n, &shut) != EV_READ) |
205 |
return; |
206 |
- default: |
207 |
- fatalx("unknown event"); |
208 |
- } |
209 |
|
210 |
for (;;) { |
211 |
if ((n = imsg_get(ibuf, &imsg)) == -1) |
212 |
@@ -401,24 +390,12 @@ ospfe_dispatch_rde(int fd, short event, void *bula) |
213 |
struct lsa_entry *le; |
214 |
struct imsg imsg; |
215 |
struct abr_rtr ar; |
216 |
- int n, noack = 0, shut = 0; |
217 |
+ int noack = 0, shut = 0; |
218 |
u_int16_t l, age; |
219 |
+ ssize_t n; |
220 |
|
221 |
- switch (event) { |
222 |
- case EV_READ: |
223 |
- if ((n = imsg_read(ibuf)) == -1) |
224 |
- fatal("imsg_read error"); |
225 |
- if (n == 0) /* connection closed */ |
226 |
- shut = 1; |
227 |
- break; |
228 |
- case EV_WRITE: |
229 |
- if (msgbuf_write(&ibuf->w) == -1) |
230 |
- fatal("msgbuf_write"); |
231 |
- imsg_event_add(ibuf); |
232 |
+ if (dispatch_read_write_event(event, ibuf, &n, &shut) != EV_READ) |
233 |
return; |
234 |
- default: |
235 |
- fatalx("unknown event"); |
236 |
- } |
237 |
|
238 |
for (;;) { |
239 |
if ((n = imsg_get(ibuf, &imsg)) == -1) |
240 |
diff --git a/ospfd/rde.c b/ospfd/rde.c |
241 |
index 5dd0623..faa0c23 100644 |
242 |
--- ospfd/rde.c |
243 |
+++ ospfd/rde.c |
244 |
@@ -37,6 +37,7 @@ |
245 |
#include "ospfe.h" |
246 |
#include "log.h" |
247 |
#include "rde.h" |
248 |
+#include "libevent_helpers.h" |
249 |
|
250 |
void rde_sig_handler(int sig, short, void *); |
251 |
void rde_shutdown(void); |
252 |
@@ -239,21 +240,8 @@ rde_dispatch_imsg(int fd, short event, void *bula) |
253 |
int r, state, self, shut = 0; |
254 |
u_int16_t l; |
255 |
|
256 |
- switch (event) { |
257 |
- case EV_READ: |
258 |
- if ((n = imsg_read(ibuf)) == -1) |
259 |
- fatal("imsg_read error"); |
260 |
- if (n == 0) /* connection closed */ |
261 |
- shut = 1; |
262 |
- break; |
263 |
- case EV_WRITE: |
264 |
- if (msgbuf_write(&ibuf->w) == -1) |
265 |
- fatal("msgbuf_write"); |
266 |
- imsg_event_add(ibuf); |
267 |
+ if (dispatch_read_write_event(event, ibuf, &n, &shut) != EV_READ) |
268 |
return; |
269 |
- default: |
270 |
- fatalx("unknown event"); |
271 |
- } |
272 |
|
273 |
clock_gettime(CLOCK_MONOTONIC, &tp); |
274 |
now = tp.tv_sec; |
275 |
@@ -584,21 +572,8 @@ rde_dispatch_parent(int fd, short event, void *bula) |
276 |
ssize_t n; |
277 |
int shut = 0; |
278 |
|
279 |
- switch (event) { |
280 |
- case EV_READ: |
281 |
- if ((n = imsg_read(ibuf)) == -1) |
282 |
- fatal("imsg_read error"); |
283 |
- if (n == 0) /* connection closed */ |
284 |
- shut = 1; |
285 |
- break; |
286 |
- case EV_WRITE: |
287 |
- if (msgbuf_write(&ibuf->w) == -1) |
288 |
- fatal("msgbuf_write"); |
289 |
- imsg_event_add(ibuf); |
290 |
+ if (dispatch_read_write_event(event, ibuf, &n, &shut) != EV_READ) |
291 |
return; |
292 |
- default: |
293 |
- fatalx("unknown event"); |
294 |
- } |
295 |
|
296 |
for (;;) { |
297 |
if ((n = imsg_get(ibuf, &imsg)) == -1) |
298 |
-- |
299 |
1.6.0.5 |
300 |
|