/src/kamailio/src/core/io_wait.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (C) 2005 iptelorg GmbH |
3 | | * |
4 | | * Permission to use, copy, modify, and distribute this software for any |
5 | | * purpose with or without fee is hereby granted, provided that the above |
6 | | * copyright notice and this permission notice appear in all copies. |
7 | | * |
8 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
9 | | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
10 | | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
11 | | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
12 | | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
13 | | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
14 | | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | | */ |
16 | | /*! |
17 | | * \file |
18 | | * \brief Kamailio core :: tcp io wait common stuff used by tcp_main.c & tcp_read.c |
19 | | * \ingroup core |
20 | | * Module: \ref core |
21 | | * \author andrei |
22 | | * |
23 | | * All the functions are inline because of speed reasons and because they are |
24 | | * used only from 2 places. |
25 | | * |
26 | | * You also have to define: |
27 | | * int handle_io(struct fd_map* fm, short events, int idx) (see below) |
28 | | * (this could be trivially replaced by a callback pointer entry attached |
29 | | * to the io_wait handler if more flexibility rather than performance |
30 | | * is needed) |
31 | | * fd_type - define to some enum of you choice and define also |
32 | | * FD_TYPE_DEFINED (if you don't do it fd_type will be defined |
33 | | * to int). 0 has a special not set/not init. meaning |
34 | | * (a lot of sanity checks and the sigio_rt code are based on |
35 | | * this assumption) |
36 | | */ |
37 | | |
38 | | #ifndef _io_wait_h |
39 | | #define _io_wait_h |
40 | | |
41 | | #include <errno.h> |
42 | | #include <string.h> |
43 | | #ifdef HAVE_SIGIO_RT |
44 | | #define __USE_GNU /* or else F_SETSIG won't be included */ |
45 | | #include <sys/types.h> /* recv */ |
46 | | #include <sys/socket.h> /* recv */ |
47 | | #include <signal.h> /* sigprocmask, sigwait a.s.o */ |
48 | | #endif |
49 | | |
50 | | #ifndef _GNU_SOURCE |
51 | | #define _GNU_SOURCE /* for POLLRDHUP on linux */ |
52 | | #endif |
53 | | #include <poll.h> |
54 | | #include <fcntl.h> |
55 | | |
56 | | #ifdef HAVE_EPOLL |
57 | | #include <sys/epoll.h> |
58 | | #endif |
59 | | #ifdef HAVE_KQUEUE |
60 | | #include <sys/types.h> /* needed on freebsd */ |
61 | | #include <sys/event.h> |
62 | | #include <sys/time.h> |
63 | | #endif |
64 | | #ifdef HAVE_DEVPOLL |
65 | | #include <sys/devpoll.h> |
66 | | #endif |
67 | | #ifdef HAVE_SELECT |
68 | | /* needed on openbsd for select*/ |
69 | | #include <sys/time.h> |
70 | | #include <sys/types.h> |
71 | | #include <unistd.h> |
72 | | /* needed according to POSIX for select*/ |
73 | | #include <sys/select.h> |
74 | | #endif |
75 | | |
76 | | #include "dprint.h" |
77 | | |
78 | | #include "poll_types.h" /* poll_types*/ |
79 | | #ifdef HAVE_SIGIO_RT |
80 | | #include "pt.h" /* mypid() */ |
81 | | #endif |
82 | | |
83 | | #include "compiler_opt.h" |
84 | | |
85 | | |
86 | | #ifdef HAVE_EPOLL |
87 | | /* fix defines for EPOLL */ |
88 | | #if defined POLLRDHUP && !defined EPOLLRDHUP |
89 | | #define EPOLLRDHUP POLLRDHUP /* should work on all linuxes */ |
90 | | #endif /* POLLRDHUP && EPOLLRDHUP */ |
91 | | #endif /* HAVE_EPOLL */ |
92 | | |
93 | | |
94 | | extern int _os_ver; /* os version number, needed to select bugs workarounds */ |
95 | | |
96 | | |
97 | | #if 0 |
98 | | enum fd_types; /* this should be defined from the including file, |
99 | | see tcp_main.c for an example, |
100 | | 0 has a special meaning: not used/empty*/ |
101 | | #endif |
102 | | |
103 | | #ifndef FD_TYPE_DEFINED |
104 | | typedef int fd_type; |
105 | | #define FD_TYPE_DEFINED |
106 | | #endif |
107 | | |
108 | | #ifdef __SUNPRO_C |
109 | | #pragma weak handle_io |
110 | | #endif |
111 | | |
112 | | /* maps a fd to some other structure; used in almost all cases |
113 | | * except epoll and maybe kqueue or /dev/poll */ |
114 | | typedef struct fd_map |
115 | | { |
116 | | int fd; /* fd no */ |
117 | | fd_type type; /* "data" type */ |
118 | | void *data; /* pointer to the corresponding structure */ |
119 | | short events; /* events we are interested int */ |
120 | | } fd_map_t; |
121 | | |
122 | | |
123 | | #ifdef HAVE_KQUEUE |
124 | | #ifndef KQ_CHANGES_ARRAY_SIZE |
125 | | #define KQ_CHANGES_ARRAY_SIZE 256 |
126 | | |
127 | | #ifdef __OS_netbsd |
128 | | #define KEV_UDATA_CAST (intptr_t) |
129 | | #else |
130 | | #define KEV_UDATA_CAST |
131 | | #endif |
132 | | |
133 | | #endif |
134 | | #endif |
135 | | |
136 | | |
137 | | /* handler structure */ |
138 | | typedef struct io_wait_handler |
139 | | { |
140 | | enum poll_types poll_method; |
141 | | int flags; |
142 | | struct fd_map *fd_hash; |
143 | | int fd_no; /* current index used in fd_array and the passed size for |
144 | | ep_array (for kq_array at least |
145 | | max(twice the size, kq_changes_size) should be |
146 | | be passed). */ |
147 | | int max_fd_no; /* maximum fd no, is also the size of fd_array, |
148 | | fd_hash and ep_array*/ |
149 | | /* common stuff for POLL, SIGIO_RT and SELECT |
150 | | * since poll support is always compiled => this will always be compiled */ |
151 | | struct pollfd *fd_array; /* used also by devpoll as devpoll array */ |
152 | | int crt_fd_array_idx; /* crt idx for which handle_io is called |
153 | | (updated also by del -> internal optimization) */ |
154 | | /* end of common stuff */ |
155 | | #ifdef HAVE_EPOLL |
156 | | int epfd; /* epoll ctrl fd */ |
157 | | struct epoll_event *ep_array; |
158 | | #endif |
159 | | #ifdef HAVE_SIGIO_RT |
160 | | sigset_t sset; /* signal mask for sigio & sigrtmin */ |
161 | | int signo; /* real time signal used */ |
162 | | #endif |
163 | | #ifdef HAVE_KQUEUE |
164 | | int kq_fd; |
165 | | struct kevent *kq_array; /* used for the eventlist*/ |
166 | | struct kevent *kq_changes; /* used for the changelist */ |
167 | | size_t kq_nchanges; |
168 | | size_t kq_array_size; /* array size */ |
169 | | size_t kq_changes_size; /* size of the changes array */ |
170 | | #endif |
171 | | #ifdef HAVE_DEVPOLL |
172 | | int dpoll_fd; |
173 | | #endif |
174 | | #ifdef HAVE_SELECT |
175 | | fd_set main_rset; /* read set */ |
176 | | fd_set main_wset; /* write set */ |
177 | | int max_fd_select; /* maximum select used fd */ |
178 | | #endif |
179 | | } io_wait_h; |
180 | | |
181 | | |
182 | | /* get the corresponding fd_map structure pointer */ |
183 | 0 | #define get_fd_map(h, fd) (&(h)->fd_hash[(fd)]) |
184 | | |
185 | | /* remove a fd_map structure from the hash; the pointer must be returned |
186 | | * by get_fd_map or hash_fd_map*/ |
187 | | #define unhash_fd_map(pfm) \ |
188 | 0 | do { \ |
189 | 0 | (pfm)->type = 0 /*F_NONE */; \ |
190 | 0 | (pfm)->fd = -1; \ |
191 | 0 | } while(0) |
192 | | |
193 | | /* add a fd_map structure to the fd hash */ |
194 | | static inline struct fd_map *hash_fd_map( |
195 | | io_wait_h *h, int fd, short events, fd_type type, void *data) |
196 | 0 | { |
197 | 0 | h->fd_hash[fd].fd = fd; |
198 | 0 | h->fd_hash[fd].events = events; |
199 | 0 | h->fd_hash[fd].type = type; |
200 | 0 | h->fd_hash[fd].data = data; |
201 | 0 | return &h->fd_hash[fd]; |
202 | 0 | } Unexecuted instantiation: tcp_main.c:hash_fd_map Unexecuted instantiation: tcp_read.c:hash_fd_map Unexecuted instantiation: io_wait.c:hash_fd_map |
203 | | |
204 | | |
205 | | #ifdef HANDLE_IO_INLINE |
206 | | /* generic handle io routine, this must be defined in the including file |
207 | | * (faster than registering a callback pointer) |
208 | | * |
209 | | * params: fm - pointer to a fd hash entry |
210 | | * events - combinations of POLLIN, POLLOUT, POLLERR & POLLHUP |
211 | | * idx - index in the fd_array (or -1 if not known) |
212 | | * return: -1 on error |
213 | | * 0 on EAGAIN or when by some other way it is known that no more |
214 | | * io events are queued on the fd (the receive buffer is empty). |
215 | | * Useful to detect when there are no more io events queued for |
216 | | * sigio_rt, epoll_et, kqueue. |
217 | | * >0 on successfull read from the fd (when there might be more io |
218 | | * queued -- the receive buffer might still be non-empty) |
219 | | */ |
220 | | inline static int handle_io(struct fd_map *fm, short events, int idx); |
221 | | #else |
222 | | int handle_io(struct fd_map *fm, short events, int idx); |
223 | | #endif |
224 | | |
225 | | |
226 | | #ifdef HAVE_KQUEUE |
227 | | /* |
228 | | * kqueue specific function: register a change |
229 | | * (adds a change to the kevent change array, and if full flushes it first) |
230 | | * |
231 | | * TODO: check if the event already exists in the change list or if it's |
232 | | * complementary to an event in the list (e.g. EVFILT_WRITE, EV_DELETE |
233 | | * and EVFILT_WRITE, EV_ADD for the same fd). |
234 | | * returns: -1 on error, 0 on success |
235 | | */ |
236 | | static inline int kq_ev_change( |
237 | | io_wait_h *h, int fd, int filter, int flag, void *data) |
238 | | { |
239 | | int n; |
240 | | int r; |
241 | | struct timespec tspec; |
242 | | |
243 | | if(h->kq_nchanges >= h->kq_changes_size) { |
244 | | /* changes array full ! */ |
245 | | LM_WARN("kqueue changes array full trying to flush...\n"); |
246 | | tspec.tv_sec = 0; |
247 | | tspec.tv_nsec = 0; |
248 | | again: |
249 | | n = kevent(h->kq_fd, h->kq_changes, h->kq_nchanges, 0, 0, &tspec); |
250 | | if(unlikely(n == -1)) { |
251 | | if(unlikely(errno == EINTR)) |
252 | | goto again; |
253 | | else { |
254 | | /* for a detailed explanation of what follows see |
255 | | io_wait_loop_kqueue EV_ERROR case */ |
256 | | if(unlikely(!(errno == EBADF || errno == ENOENT))) |
257 | | BUG("kq_ev_change: kevent flush changes failed" |
258 | | " (unexpected error): %s [%d]\n", |
259 | | strerror(errno), errno); |
260 | | /* ignore error even if it's not an EBADF/ENOENT */ |
261 | | /* one of the file descriptors is bad, probably already |
262 | | closed => try to apply changes one-by-one */ |
263 | | for(r = 0; r < h->kq_nchanges; r++) { |
264 | | retry2: |
265 | | n = kevent(h->kq_fd, &h->kq_changes[r], 1, 0, 0, &tspec); |
266 | | if(n == -1) { |
267 | | if(unlikely(errno == EINTR)) |
268 | | goto retry2; |
269 | | /* for a detailed explanation of what follows see |
270 | | io_wait_loop_kqueue EV_ERROR case */ |
271 | | if(unlikely(!(errno == EBADF || errno == ENOENT))) |
272 | | BUG("kq_ev_change: kevent flush changes failed:" |
273 | | " (unexpected error) %s [%d] (%d/%lu)\n", |
274 | | strerror(errno), errno, r, |
275 | | (unsigned long)h->kq_nchanges); |
276 | | continue; /* skip over it */ |
277 | | } |
278 | | } |
279 | | } |
280 | | } |
281 | | h->kq_nchanges = 0; /* changes array is empty */ |
282 | | } |
283 | | EV_SET(&h->kq_changes[h->kq_nchanges], fd, filter, flag, 0, 0, |
284 | | KEV_UDATA_CAST data); |
285 | | h->kq_nchanges++; |
286 | | return 0; |
287 | | } |
288 | | #endif |
289 | | |
290 | | |
291 | | /* generic io_watch_add function |
292 | | * Params: |
293 | | * h - pointer to initialized io_wait handle |
294 | | * fd - fd to watch |
295 | | * events - bitmap with the fd events for which the fd should be watched |
296 | | * (combination of POLLIN and POLLOUT) |
297 | | * type - fd type (non 0 value, returned in the call to handle_io) |
298 | | * data - pointer/private data returned in the handle_io call |
299 | | * returns 0 on success, -1 on error |
300 | | * |
301 | | * WARNING: handle_io() can be called immediately (from io_watch_add()) so |
302 | | * make sure that any dependent init. (e.g. data stuff) is made before |
303 | | * calling io_watch_add |
304 | | * |
305 | | * this version should be faster than pointers to poll_method specific |
306 | | * functions (it avoids functions calls, the overhead being only an extra |
307 | | * switch())*/ |
308 | | inline static int io_watch_add( |
309 | | io_wait_h *h, int fd, short events, fd_type type, void *data) |
310 | 0 | { |
311 | | |
312 | | /* helper macros */ |
313 | 0 | #define fd_array_setup(ev) \ |
314 | 0 | do { \ |
315 | 0 | h->fd_array[h->fd_no].fd = fd; \ |
316 | 0 | h->fd_array[h->fd_no].events = (ev); /* useless for select */ \ |
317 | 0 | h->fd_array[h->fd_no].revents = 0; /* useless for select */ \ |
318 | 0 | } while(0) |
319 | |
|
320 | 0 | #define set_fd_flags(f) \ |
321 | 0 | do { \ |
322 | 0 | flags = fcntl(fd, F_GETFL); \ |
323 | 0 | if(flags == -1) { \ |
324 | 0 | LM_ERR("fnctl: GETFL failed: %s [%d]\n", strerror(errno), errno); \ |
325 | 0 | goto error; \ |
326 | 0 | } \ |
327 | 0 | if(fcntl(fd, F_SETFL, flags | (f)) == -1) { \ |
328 | 0 | LM_ERR("fnctl: SETFL failed: %s [%d]\n", strerror(errno), errno); \ |
329 | 0 | goto error; \ |
330 | 0 | } \ |
331 | 0 | } while(0) |
332 | |
|
333 | 0 | struct fd_map *e; |
334 | 0 | int flags; |
335 | 0 | #ifdef HAVE_EPOLL |
336 | 0 | struct epoll_event ep_event; |
337 | 0 | #endif |
338 | | #ifdef HAVE_DEVPOLL |
339 | | struct pollfd pfd; |
340 | | #endif |
341 | 0 | #if defined(HAVE_SIGIO_RT) || defined(HAVE_EPOLL) |
342 | 0 | int n; |
343 | 0 | #endif |
344 | 0 | #if defined(HAVE_SIGIO_RT) |
345 | 0 | int idx; |
346 | 0 | int check_io; |
347 | 0 | struct pollfd pf; |
348 | |
|
349 | 0 | check_io = 0; /* set to 1 if we need to check for pre-existing queued |
350 | | io/data on the fd */ |
351 | 0 | idx = -1; |
352 | 0 | #endif |
353 | 0 | e = 0; |
354 | | /* sanity checks */ |
355 | 0 | if(unlikely(fd == -1)) { |
356 | 0 | LM_CRIT("fd is -1!\n"); |
357 | 0 | goto error; |
358 | 0 | } |
359 | 0 | if(unlikely((events & (POLLIN | POLLOUT)) == 0)) { |
360 | 0 | LM_CRIT("invalid events: 0x%0x\n", events); |
361 | 0 | goto error; |
362 | 0 | } |
363 | | /* check if not too big */ |
364 | 0 | if(unlikely(h->fd_no >= h->max_fd_no)) { |
365 | 0 | LM_CRIT("maximum fd number exceeded: %d/%d\n", h->fd_no, h->max_fd_no); |
366 | 0 | goto error; |
367 | 0 | } |
368 | 0 | DBG("processing io_watch_add(%p, %d, %d, %p) - fd_no=%d\n", h, fd, type, |
369 | 0 | data, h->fd_no); |
370 | | /* hash sanity check */ |
371 | 0 | e = get_fd_map(h, fd); |
372 | 0 | if(unlikely(e && (e->type != 0 /*F_NONE*/))) { |
373 | 0 | LM_ERR("trying to overwrite entry %d watched for %x" |
374 | 0 | " in the hash %p (fd:%d, type:%d, data:%p) with (%d, %d, %p)\n", |
375 | 0 | fd, events, h, e->fd, e->type, e->data, fd, type, data); |
376 | 0 | e = 0; |
377 | 0 | goto error; |
378 | 0 | } |
379 | | |
380 | 0 | if(unlikely((e = hash_fd_map(h, fd, events, type, data)) == 0)) { |
381 | 0 | LM_ERR("failed to hash the fd %d\n", fd); |
382 | 0 | goto error; |
383 | 0 | } |
384 | 0 | switch(h->poll_method) { /* faster than pointer to functions */ |
385 | 0 | case POLL_POLL: |
386 | 0 | #ifdef POLLRDHUP |
387 | | /* listen to POLLRDHUP by default (if POLLIN) */ |
388 | 0 | events |= ((int)!(events & POLLIN) - 1) & POLLRDHUP; |
389 | 0 | #endif /* POLLRDHUP */ |
390 | 0 | fd_array_setup(events); |
391 | 0 | set_fd_flags(O_NONBLOCK); |
392 | 0 | break; |
393 | 0 | #ifdef HAVE_SELECT |
394 | 0 | case POLL_SELECT: |
395 | 0 | fd_array_setup(events); |
396 | 0 | if(likely(events & POLLIN)) |
397 | 0 | FD_SET(fd, &h->main_rset); |
398 | 0 | if(unlikely(events & POLLOUT)) |
399 | 0 | FD_SET(fd, &h->main_wset); |
400 | 0 | if(h->max_fd_select < fd) |
401 | 0 | h->max_fd_select = fd; |
402 | 0 | break; |
403 | 0 | #endif |
404 | 0 | #ifdef HAVE_SIGIO_RT |
405 | 0 | case POLL_SIGIO_RT: |
406 | 0 | fd_array_setup(events); |
407 | | /* re-set O_ASYNC might be needed, if not done from |
408 | | * io_watch_del (or if somebody wants to add a fd which has |
409 | | * already O_ASYNC/F_SETSIG set on a duplicate) |
410 | | */ |
411 | | /* set async & signal */ |
412 | 0 | if(fcntl(fd, F_SETOWN, my_pid()) == -1) { |
413 | 0 | LM_ERR("fnctl: SETOWN on fd %d failed: %s [%d]\n", fd, |
414 | 0 | strerror(errno), errno); |
415 | 0 | goto error; |
416 | 0 | } |
417 | 0 | if(fcntl(fd, F_SETSIG, h->signo) == -1) { |
418 | 0 | LM_ERR("fnctl: SETSIG on fd %d failed: %s [%d]\n", fd, |
419 | 0 | strerror(errno), errno); |
420 | 0 | goto error; |
421 | 0 | } |
422 | | /* set both non-blocking and async */ |
423 | 0 | set_fd_flags(O_ASYNC | O_NONBLOCK); |
424 | | #ifdef EXTRA_DEBUG |
425 | | DBG("io_watch_add: sigio_rt on f %d, signal %d to pid %d\n", fd, |
426 | | h->signo, my_pid()); |
427 | | #endif |
428 | | /* empty socket receive buffer, if buffer is already full |
429 | | * no more space to put packets |
430 | | * => no more signals are ever generated |
431 | | * also when moving fds, the freshly moved fd might have |
432 | | * already some bytes queued, we want to get them now |
433 | | * and not later -- andrei */ |
434 | 0 | idx = h->fd_no; |
435 | 0 | check_io = 1; |
436 | 0 | break; |
437 | 0 | #endif |
438 | 0 | #ifdef HAVE_EPOLL |
439 | 0 | case POLL_EPOLL_LT: |
440 | 0 | ep_event.events = |
441 | 0 | #ifdef POLLRDHUP |
442 | | /* listen for EPOLLRDHUP too */ |
443 | 0 | ((EPOLLIN | EPOLLRDHUP) & ((int)!(events & POLLIN) - 1)) | |
444 | | #else /* POLLRDHUP */ |
445 | | (EPOLLIN & ((int)!(events & POLLIN) - 1)) | |
446 | | #endif /* POLLRDHUP */ |
447 | 0 | (EPOLLOUT & ((int)!(events & POLLOUT) - 1)); |
448 | 0 | ep_event.data.ptr = e; |
449 | 0 | again1: |
450 | 0 | n = epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event); |
451 | 0 | if(unlikely(n == -1)) { |
452 | 0 | if(errno == EAGAIN) |
453 | 0 | goto again1; |
454 | 0 | LM_ERR("epoll_ctl on fd %d failed: %s [%d]\n", fd, |
455 | 0 | strerror(errno), errno); |
456 | 0 | goto error; |
457 | 0 | } |
458 | 0 | break; |
459 | 0 | case POLL_EPOLL_ET: |
460 | 0 | set_fd_flags(O_NONBLOCK); |
461 | 0 | ep_event.events = |
462 | 0 | #ifdef POLLRDHUP |
463 | | /* listen for EPOLLRDHUP too */ |
464 | 0 | ((EPOLLIN | EPOLLRDHUP) & ((int)!(events & POLLIN) - 1)) | |
465 | | #else /* POLLRDHUP */ |
466 | | (EPOLLIN & ((int)!(events & POLLIN) - 1)) | |
467 | | #endif /* POLLRDHUP */ |
468 | 0 | (EPOLLOUT & ((int)!(events & POLLOUT) - 1)) | EPOLLET; |
469 | 0 | ep_event.data.ptr = e; |
470 | 0 | again2: |
471 | 0 | n = epoll_ctl(h->epfd, EPOLL_CTL_ADD, fd, &ep_event); |
472 | 0 | if(unlikely(n == -1)) { |
473 | 0 | if(errno == EAGAIN) |
474 | 0 | goto again2; |
475 | 0 | LM_ERR("epoll_ctl on fd %d failed: %s [%d]\n", fd, |
476 | 0 | strerror(errno), errno); |
477 | 0 | goto error; |
478 | 0 | } |
479 | 0 | break; |
480 | 0 | #endif |
481 | | #ifdef HAVE_KQUEUE |
482 | | case POLL_KQUEUE: |
483 | | if(likely(events & POLLIN)) { |
484 | | if(unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e) == -1)) |
485 | | goto error; |
486 | | } |
487 | | if(unlikely(events & POLLOUT)) { |
488 | | if(unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e) |
489 | | == -1)) { |
490 | | if(likely(events & POLLIN)) { |
491 | | kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0); |
492 | | } |
493 | | goto error; |
494 | | } |
495 | | } |
496 | | break; |
497 | | #endif |
498 | | #ifdef HAVE_DEVPOLL |
499 | | case POLL_DEVPOLL: |
500 | | pfd.fd = fd; |
501 | | pfd.events = events; |
502 | | pfd.revents = 0; |
503 | | again_devpoll: |
504 | | if(write(h->dpoll_fd, &pfd, sizeof(pfd)) == -1) { |
505 | | if(errno == EAGAIN) |
506 | | goto again_devpoll; |
507 | | LM_ERR("/dev/poll write of fd %d failed: %s [%d]\n", fd, |
508 | | strerror(errno), errno); |
509 | | goto error; |
510 | | } |
511 | | break; |
512 | | #endif |
513 | | |
514 | 0 | default: |
515 | 0 | LM_CRIT("no support for poll method %s (%d)\n", |
516 | 0 | poll_method_str[h->poll_method], h->poll_method); |
517 | 0 | goto error; |
518 | 0 | } |
519 | | |
520 | 0 | h->fd_no++; /* "activate" changes, for epoll/kqueue/devpoll it |
521 | | has only informative value */ |
522 | 0 | #if defined(HAVE_SIGIO_RT) |
523 | 0 | if(check_io) { |
524 | | /* handle possible pre-existing events */ |
525 | 0 | pf.fd = fd; |
526 | 0 | pf.events = events; |
527 | 0 | check_io_again: |
528 | 0 | n = 0; |
529 | 0 | while(e->type && ((n = poll(&pf, 1, 0)) > 0) |
530 | 0 | && (handle_io(e, pf.revents, idx) > 0) |
531 | 0 | && (pf.revents & (e->events | POLLERR | POLLHUP))) |
532 | 0 | ; |
533 | 0 | if(unlikely(e->type && (n == -1))) { |
534 | 0 | if(errno == EINTR) |
535 | 0 | goto check_io_again; |
536 | 0 | LM_ERR("check_io poll on fd %d failed: %s [%d]\n", fd, |
537 | 0 | strerror(errno), errno); |
538 | 0 | } |
539 | 0 | } |
540 | 0 | #endif |
541 | 0 | return 0; |
542 | 0 | error: |
543 | 0 | if(e) |
544 | 0 | unhash_fd_map(e); |
545 | 0 | return -1; |
546 | 0 | #undef fd_array_setup |
547 | 0 | #undef set_fd_flags |
548 | 0 | } Unexecuted instantiation: tcp_main.c:io_watch_add Unexecuted instantiation: tcp_read.c:io_watch_add Unexecuted instantiation: io_wait.c:io_watch_add |
549 | | |
550 | | |
551 | 0 | #define IO_FD_CLOSING 16 |
552 | | /* parameters: h - handler |
553 | | * fd - file descriptor |
554 | | * index - index in the fd_array if known, -1 if not |
555 | | * (if index==-1 fd_array will be searched for the |
556 | | * corresponding fd* entry -- slower but unavoidable in |
557 | | * some cases). index is not used (no fd_array) for epoll, |
558 | | * /dev/poll and kqueue |
559 | | * flags - optimization flags, e.g. IO_FD_CLOSING, the fd was |
560 | | * or will shortly be closed, in some cases we can avoid |
561 | | * extra remove operations (e.g.: epoll, kqueue, sigio) |
562 | | * returns 0 if ok, -1 on error */ |
563 | | inline static int io_watch_del(io_wait_h *h, int fd, int idx, int flags) |
564 | 0 | { |
565 | |
|
566 | 0 | #define fix_fd_array \ |
567 | 0 | do { \ |
568 | 0 | if(unlikely(idx == -1)) { \ |
569 | | /* fix idx if -1 and needed */ \ |
570 | 0 | for(idx = 0; (idx < h->fd_no) && (h->fd_array[idx].fd != fd); \ |
571 | 0 | idx++) \ |
572 | 0 | ; \ |
573 | 0 | } \ |
574 | 0 | if(likely(idx < h->fd_no)) { \ |
575 | 0 | memmove(&h->fd_array[idx], &h->fd_array[idx + 1], \ |
576 | 0 | (h->fd_no - (idx + 1)) * sizeof(*(h->fd_array))); \ |
577 | 0 | if((idx <= h->crt_fd_array_idx) && (h->crt_fd_array_idx >= 0)) \ |
578 | 0 | h->crt_fd_array_idx--; \ |
579 | 0 | } \ |
580 | 0 | } while(0) |
581 | |
|
582 | 0 | struct fd_map *e; |
583 | 0 | int events; |
584 | 0 | #ifdef HAVE_EPOLL |
585 | 0 | int n; |
586 | 0 | struct epoll_event ep_event; |
587 | 0 | #endif |
588 | | #ifdef HAVE_DEVPOLL |
589 | | struct pollfd pfd; |
590 | | #endif |
591 | 0 | #ifdef HAVE_SIGIO_RT |
592 | 0 | int fd_flags; |
593 | 0 | #endif |
594 | |
|
595 | 0 | if(unlikely((fd < 0) || (fd >= h->max_fd_no))) { |
596 | 0 | LM_CRIT("invalid fd %d, not in [0, %d) \n", fd, h->fd_no); |
597 | 0 | goto error; |
598 | 0 | } |
599 | 0 | DBG("DBG: io_watch_del (%p, %d, %d, 0x%x) fd_no=%d called\n", h, fd, idx, |
600 | 0 | flags, h->fd_no); |
601 | 0 | e = get_fd_map(h, fd); |
602 | | /* more sanity checks */ |
603 | 0 | if(unlikely(e == 0)) { |
604 | 0 | LM_CRIT("no corresponding hash entry for %d\n", fd); |
605 | 0 | goto error; |
606 | 0 | } |
607 | 0 | if(unlikely(e->type == 0 /*F_NONE*/)) { |
608 | 0 | LM_ERR("trying to delete already erased" |
609 | 0 | " entry %d in the hash(%d, %d, %p) flags %x)\n", |
610 | 0 | fd, e->fd, e->type, e->data, flags); |
611 | 0 | goto error; |
612 | 0 | } |
613 | 0 | events = e->events; |
614 | |
|
615 | 0 | switch(h->poll_method) { |
616 | 0 | case POLL_POLL: |
617 | 0 | fix_fd_array; |
618 | 0 | break; |
619 | 0 | #ifdef HAVE_SELECT |
620 | 0 | case POLL_SELECT: |
621 | 0 | if(likely(events & POLLIN)) |
622 | 0 | FD_CLR(fd, &h->main_rset); |
623 | 0 | if(unlikely(events & POLLOUT)) |
624 | 0 | FD_CLR(fd, &h->main_wset); |
625 | 0 | if(unlikely(h->max_fd_select && (h->max_fd_select == fd))) |
626 | | /* we don't know the prev. max, so we just decrement it */ |
627 | 0 | h->max_fd_select--; |
628 | 0 | fix_fd_array; |
629 | 0 | break; |
630 | 0 | #endif |
631 | 0 | #ifdef HAVE_SIGIO_RT |
632 | 0 | case POLL_SIGIO_RT: |
633 | | /* the O_ASYNC flag must be reset all the time, the fd |
634 | | * can be changed only if O_ASYNC is reset (if not and |
635 | | * the fd is a duplicate, you will get signals from the dup. fd |
636 | | * and not from the original, even if the dup. fd was closed |
637 | | * and the signals re-set on the original) -- andrei |
638 | | */ |
639 | | /*if (!(flags & IO_FD_CLOSING)){*/ |
640 | | /* reset ASYNC */ |
641 | 0 | fd_flags = fcntl(fd, F_GETFL); |
642 | 0 | if(unlikely(fd_flags == -1)) { |
643 | 0 | LM_ERR("fnctl: GETFL on fd %d failed: %s [%d]\n", fd, |
644 | 0 | strerror(errno), errno); |
645 | 0 | goto error; |
646 | 0 | } |
647 | 0 | if(unlikely(fcntl(fd, F_SETFL, fd_flags & (~O_ASYNC)) == -1)) { |
648 | 0 | LM_ERR("fnctl: SETFL on fd %d failed: %s [%d]\n", fd, |
649 | 0 | strerror(errno), errno); |
650 | 0 | goto error; |
651 | 0 | } |
652 | 0 | fix_fd_array; /* only on success */ |
653 | 0 | break; |
654 | 0 | #endif |
655 | 0 | #ifdef HAVE_EPOLL |
656 | 0 | case POLL_EPOLL_LT: |
657 | 0 | case POLL_EPOLL_ET: |
658 | | /* epoll doesn't seem to automatically remove sockets, |
659 | | * if the socket is a duplicate/moved and the original |
660 | | * is still open. The fd is removed from the epoll set |
661 | | * only when the original (and all the copies?) is/are |
662 | | * closed. This is probably a bug in epoll. --andrei */ |
663 | | #ifdef EPOLL_NO_CLOSE_BUG |
664 | | if(!(flags & IO_FD_CLOSING)) { |
665 | | #endif |
666 | 0 | again_epoll: |
667 | 0 | n = epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event); |
668 | 0 | if(unlikely(n == -1)) { |
669 | 0 | if(errno == EAGAIN) |
670 | 0 | goto again_epoll; |
671 | 0 | LM_ERR("removing fd %d from epoll list failed: %s [%d]\n", |
672 | 0 | fd, strerror(errno), errno); |
673 | 0 | if(unlikely(errno == EBADF)) { |
674 | 0 | LM_ERR("unhashing of invalid fd - %d (epfd %d)\n", fd, |
675 | 0 | h->epfd); |
676 | 0 | unhash_fd_map(e); |
677 | 0 | h->fd_no--; |
678 | 0 | } |
679 | |
|
680 | 0 | goto error; |
681 | 0 | } |
682 | | #ifdef EPOLL_NO_CLOSE_BUG |
683 | | } |
684 | | #endif |
685 | 0 | break; |
686 | 0 | #endif |
687 | | #ifdef HAVE_KQUEUE |
688 | | case POLL_KQUEUE: |
689 | | if(!(flags & IO_FD_CLOSING)) { |
690 | | if(likely(events & POLLIN)) { |
691 | | if(unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0) |
692 | | == -1)) { |
693 | | /* try to delete the write filter anyway */ |
694 | | if(events & POLLOUT) { |
695 | | kq_ev_change(h, fd, EVFILT_WRITE, EV_DELETE, 0); |
696 | | } |
697 | | goto error; |
698 | | } |
699 | | } |
700 | | if(unlikely(events & POLLOUT)) { |
701 | | if(unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_DELETE, 0) |
702 | | == -1)) |
703 | | goto error; |
704 | | } |
705 | | } |
706 | | break; |
707 | | #endif |
708 | | #ifdef HAVE_DEVPOLL |
709 | | case POLL_DEVPOLL: |
710 | | /* for /dev/poll the closed fds _must_ be removed |
711 | | (they are not removed automatically on close()) */ |
712 | | pfd.fd = fd; |
713 | | pfd.events = POLLREMOVE; |
714 | | pfd.revents = 0; |
715 | | again_devpoll: |
716 | | if(write(h->dpoll_fd, &pfd, sizeof(pfd)) == -1) { |
717 | | if(errno == EINTR) |
718 | | goto again_devpoll; |
719 | | LM_ERR("removing fd %d from /dev/poll failed: %s [%d]\n", fd, |
720 | | strerror(errno), errno); |
721 | | goto error; |
722 | | } |
723 | | break; |
724 | | #endif |
725 | 0 | default: |
726 | 0 | LM_CRIT("no support for poll method %s (%d)\n", |
727 | 0 | poll_method_str[h->poll_method], h->poll_method); |
728 | 0 | goto error; |
729 | 0 | } |
730 | 0 | unhash_fd_map(e); /* only on success */ |
731 | 0 | h->fd_no--; |
732 | 0 | return 0; |
733 | 0 | error: |
734 | 0 | return -1; |
735 | 0 | #undef fix_fd_array |
736 | 0 | } Unexecuted instantiation: tcp_main.c:io_watch_del Unexecuted instantiation: tcp_read.c:io_watch_del Unexecuted instantiation: io_wait.c:io_watch_del |
737 | | |
738 | | |
739 | | /* parameters: h - handler |
740 | | * fd - file descriptor |
741 | | * events - new events to watch for |
742 | | * idx - index in the fd_array if known, -1 if not |
743 | | * (if index==-1 fd_array will be searched for the |
744 | | * corresponding fd* entry -- slower but unavoidable in |
745 | | * some cases). index is not used (no fd_array) for epoll, |
746 | | * /dev/poll and kqueue |
747 | | * returns 0 if ok, -1 on error */ |
748 | | inline static int io_watch_chg(io_wait_h *h, int fd, short events, int idx) |
749 | 0 | { |
750 | |
|
751 | 0 | #define fd_array_chg(ev) \ |
752 | 0 | do { \ |
753 | 0 | if(unlikely(idx == -1)) { \ |
754 | | /* fix idx if -1 and needed */ \ |
755 | 0 | for(idx = 0; (idx < h->fd_no) && (h->fd_array[idx].fd != fd); \ |
756 | 0 | idx++) \ |
757 | 0 | ; \ |
758 | 0 | } \ |
759 | 0 | if(likely(idx < h->fd_no)) { \ |
760 | 0 | h->fd_array[idx].events = (ev); \ |
761 | 0 | } \ |
762 | 0 | } while(0) |
763 | |
|
764 | 0 | struct fd_map *e; |
765 | 0 | int add_events; |
766 | 0 | int del_events; |
767 | | #ifdef HAVE_DEVPOLL |
768 | | struct pollfd pfd; |
769 | | #endif |
770 | 0 | #ifdef HAVE_EPOLL |
771 | 0 | int n; |
772 | 0 | struct epoll_event ep_event; |
773 | 0 | #endif |
774 | |
|
775 | 0 | if(unlikely((fd < 0) || (fd >= h->max_fd_no))) { |
776 | 0 | LM_CRIT("invalid fd %d, not in [0, %d) \n", fd, h->fd_no); |
777 | 0 | goto error; |
778 | 0 | } |
779 | 0 | if(unlikely((events & (POLLIN | POLLOUT)) == 0)) { |
780 | 0 | LM_CRIT("invalid events: 0x%0x\n", events); |
781 | 0 | goto error; |
782 | 0 | } |
783 | 0 | DBG("DBG: io_watch_chg (%p, %d, 0x%x, 0x%x) fd_no=%d called\n", h, fd, |
784 | 0 | events, idx, h->fd_no); |
785 | 0 | e = get_fd_map(h, fd); |
786 | | /* more sanity checks */ |
787 | 0 | if(unlikely(e == 0)) { |
788 | 0 | LM_CRIT("no corresponding hash entry for %d\n", fd); |
789 | 0 | goto error; |
790 | 0 | } |
791 | 0 | if(unlikely(e->type == 0 /*F_NONE*/)) { |
792 | 0 | LM_ERR("trying to change an already erased" |
793 | 0 | " entry %d in the hash(%d, %d, %p) )\n", |
794 | 0 | fd, e->fd, e->type, e->data); |
795 | 0 | goto error; |
796 | 0 | } |
797 | | |
798 | 0 | add_events = events & ~e->events; |
799 | 0 | del_events = e->events & ~events; |
800 | 0 | switch(h->poll_method) { |
801 | 0 | case POLL_POLL: |
802 | 0 | #ifdef POLLRDHUP |
803 | 0 | fd_array_chg(events | |
804 | | /* listen to POLLRDHUP by default (if POLLIN) */ |
805 | 0 | (((int)!(events & POLLIN) - 1) & POLLRDHUP)); |
806 | | #else /* POLLRDHUP */ |
807 | | fd_array_chg(events); |
808 | | #endif /* POLLRDHUP */ |
809 | 0 | break; |
810 | 0 | #ifdef HAVE_SELECT |
811 | 0 | case POLL_SELECT: |
812 | 0 | fd_array_chg(events); |
813 | 0 | if(unlikely(del_events & POLLIN)) |
814 | 0 | FD_CLR(fd, &h->main_rset); |
815 | 0 | else if(unlikely(add_events & POLLIN)) |
816 | 0 | FD_SET(fd, &h->main_rset); |
817 | 0 | if(likely(del_events & POLLOUT)) |
818 | 0 | FD_CLR(fd, &h->main_wset); |
819 | 0 | else if(likely(add_events & POLLOUT)) |
820 | 0 | FD_SET(fd, &h->main_wset); |
821 | 0 | break; |
822 | 0 | #endif |
823 | 0 | #ifdef HAVE_SIGIO_RT |
824 | 0 | case POLL_SIGIO_RT: |
825 | 0 | fd_array_chg(events); |
826 | | /* no need for check_io, since SIGIO_RT listens by default for all |
827 | | * the events */ |
828 | 0 | break; |
829 | 0 | #endif |
830 | 0 | #ifdef HAVE_EPOLL |
831 | 0 | case POLL_EPOLL_LT: |
832 | 0 | ep_event.events = |
833 | 0 | #ifdef POLLRDHUP |
834 | | /* listen for EPOLLRDHUP too */ |
835 | 0 | ((EPOLLIN | EPOLLRDHUP) & ((int)!(events & POLLIN) - 1)) | |
836 | | #else /* POLLRDHUP */ |
837 | | (EPOLLIN & ((int)!(events & POLLIN) - 1)) | |
838 | | #endif /* POLLRDHUP */ |
839 | 0 | (EPOLLOUT & ((int)!(events & POLLOUT) - 1)); |
840 | 0 | ep_event.data.ptr = e; |
841 | 0 | again_epoll_lt: |
842 | 0 | n = epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event); |
843 | 0 | if(unlikely(n == -1)) { |
844 | 0 | if(errno == EAGAIN) |
845 | 0 | goto again_epoll_lt; |
846 | 0 | LM_ERR("modifying epoll events of fd %d failed: %s [%d]\n", fd, |
847 | 0 | strerror(errno), errno); |
848 | 0 | goto error; |
849 | 0 | } |
850 | 0 | break; |
851 | 0 | case POLL_EPOLL_ET: |
852 | 0 | ep_event.events = |
853 | 0 | #ifdef POLLRDHUP |
854 | | /* listen for EPOLLRDHUP too */ |
855 | 0 | ((EPOLLIN | EPOLLRDHUP) & ((int)!(events & POLLIN) - 1)) | |
856 | | #else /* POLLRDHUP */ |
857 | | (EPOLLIN & ((int)!(events & POLLIN) - 1)) | |
858 | | #endif /* POLLRDHUP */ |
859 | 0 | (EPOLLOUT & ((int)!(events & POLLOUT) - 1)) | EPOLLET; |
860 | 0 | ep_event.data.ptr = e; |
861 | 0 | again_epoll_et: |
862 | 0 | n = epoll_ctl(h->epfd, EPOLL_CTL_MOD, fd, &ep_event); |
863 | 0 | if(unlikely(n == -1)) { |
864 | 0 | if(errno == EAGAIN) |
865 | 0 | goto again_epoll_et; |
866 | 0 | LM_ERR("modifying epoll events of fd %d failed: %s [%d]\n", fd, |
867 | 0 | strerror(errno), errno); |
868 | 0 | goto error; |
869 | 0 | } |
870 | 0 | break; |
871 | 0 | #endif |
872 | | #ifdef HAVE_KQUEUE |
873 | | case POLL_KQUEUE: |
874 | | if(unlikely(del_events & POLLIN)) { |
875 | | if(unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_DELETE, 0) |
876 | | == -1)) |
877 | | goto error; |
878 | | } else if(unlikely(add_events & POLLIN)) { |
879 | | if(unlikely(kq_ev_change(h, fd, EVFILT_READ, EV_ADD, e) == -1)) |
880 | | goto error; |
881 | | } |
882 | | if(likely(del_events & POLLOUT)) { |
883 | | if(unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_DELETE, 0) |
884 | | == -1)) |
885 | | goto error; |
886 | | } else if(likely(add_events & POLLOUT)) { |
887 | | if(unlikely(kq_ev_change(h, fd, EVFILT_WRITE, EV_ADD, e) == -1)) |
888 | | goto error; |
889 | | } |
890 | | break; |
891 | | #endif |
892 | | #ifdef HAVE_DEVPOLL |
893 | | case POLL_DEVPOLL: |
894 | | /* for /dev/poll the closed fds _must_ be removed |
895 | | (they are not removed automatically on close()) */ |
896 | | pfd.fd = fd; |
897 | | pfd.events = POLLREMOVE; |
898 | | pfd.revents = 0; |
899 | | again_devpoll1: |
900 | | if(unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd)) == -1)) { |
901 | | if(errno == EINTR) |
902 | | goto again_devpoll1; |
903 | | LM_ERR("removing fd %d from /dev/poll failed: %s [%d]\n", fd, |
904 | | strerror(errno), errno); |
905 | | goto error; |
906 | | } |
907 | | again_devpoll2: |
908 | | pfd.events = events; |
909 | | pfd.revents = 0; |
910 | | if(unlikely(write(h->dpoll_fd, &pfd, sizeof(pfd)) == -1)) { |
911 | | if(errno == EINTR) |
912 | | goto again_devpoll2; |
913 | | LM_ERR("re-adding fd %d to /dev/poll failed: %s [%d]\n", fd, |
914 | | strerror(errno), errno); |
915 | | /* error re-adding the fd => mark it as removed/unhash */ |
916 | | unhash_fd_map(e); |
917 | | goto error; |
918 | | } |
919 | | break; |
920 | | #endif |
921 | 0 | default: |
922 | 0 | LM_CRIT("no support for poll method %s (%d)\n", |
923 | 0 | poll_method_str[h->poll_method], h->poll_method); |
924 | 0 | goto error; |
925 | 0 | } |
926 | 0 | e->events = events; /* only on success */ |
927 | 0 | return 0; |
928 | 0 | error: |
929 | 0 | return -1; |
930 | 0 | #undef fix_fd_array |
931 | 0 | } Unexecuted instantiation: tcp_main.c:io_watch_chg Unexecuted instantiation: tcp_read.c:io_watch_chg Unexecuted instantiation: io_wait.c:io_watch_chg |
932 | | |
933 | | |
934 | | /* io_wait_loop_x style function. |
935 | | * wait for io using poll() |
936 | | * params: h - io_wait handle |
937 | | * t - timeout in s |
938 | | * repeat - if !=0 handle_io will be called until it returns <=0 |
939 | | * returns: number of IO events handled on success (can be 0), -1 on error |
940 | | */ |
941 | | inline static int io_wait_loop_poll(io_wait_h *h, int t, int repeat) |
942 | 0 | { |
943 | 0 | int n, r; |
944 | 0 | int ret; |
945 | 0 | struct fd_map *fm; |
946 | |
|
947 | 0 | again: |
948 | 0 | ret = n = poll(h->fd_array, h->fd_no, t * 1000); |
949 | 0 | if(n == -1) { |
950 | 0 | if(errno == EINTR) |
951 | 0 | goto again; /* signal, ignore it */ |
952 | 0 | else { |
953 | 0 | LM_ERR("poll: %s [%d]\n", strerror(errno), errno); |
954 | 0 | goto error; |
955 | 0 | } |
956 | 0 | } |
957 | 0 | for(r = 0; (r < h->fd_no) && n; r++) { |
958 | 0 | fm = get_fd_map(h, h->fd_array[r].fd); |
959 | 0 | if(h->fd_array[r].revents & (fm->events | POLLERR | POLLHUP)) { |
960 | 0 | n--; |
961 | | /* sanity checks */ |
962 | 0 | if(unlikely((h->fd_array[r].fd >= h->max_fd_no) |
963 | 0 | || (h->fd_array[r].fd < 0))) { |
964 | 0 | LM_CRIT("bad fd %d (no in the 0 - %d range)\n", |
965 | 0 | h->fd_array[r].fd, h->max_fd_no); |
966 | | /* try to continue anyway */ |
967 | 0 | h->fd_array[r].events = 0; /* clear the events */ |
968 | 0 | continue; |
969 | 0 | } |
970 | 0 | h->crt_fd_array_idx = r; |
971 | | /* repeat handle_io if repeat, fd still watched (not deleted |
972 | | * inside handle_io), handle_io returns that there's still |
973 | | * IO and the fd is still watched for the triggering event */ |
974 | 0 | while(fm->type && (handle_io(fm, h->fd_array[r].revents, r) > 0) |
975 | 0 | && repeat |
976 | 0 | && ((fm->events | POLLERR | POLLHUP) |
977 | 0 | & h->fd_array[r].revents)) |
978 | 0 | ; |
979 | 0 | r = h->crt_fd_array_idx; /* can change due to io_watch_del(fd) |
980 | | array shifting */ |
981 | 0 | } |
982 | 0 | } |
983 | 0 | error: |
984 | 0 | return ret; |
985 | 0 | } Unexecuted instantiation: tcp_main.c:io_wait_loop_poll Unexecuted instantiation: tcp_read.c:io_wait_loop_poll Unexecuted instantiation: io_wait.c:io_wait_loop_poll |
986 | | |
987 | | |
988 | | #ifdef HAVE_SELECT |
989 | | /* wait for io using select */ |
990 | | inline static int io_wait_loop_select(io_wait_h *h, int t, int repeat) |
991 | 0 | { |
992 | 0 | fd_set sel_rset; |
993 | 0 | fd_set sel_wset; |
994 | 0 | int n, ret; |
995 | 0 | struct timeval timeout; |
996 | 0 | int r; |
997 | 0 | struct fd_map *fm; |
998 | 0 | int revents; |
999 | |
|
1000 | 0 | again: |
1001 | 0 | sel_rset = h->main_rset; |
1002 | 0 | sel_wset = h->main_wset; |
1003 | 0 | timeout.tv_sec = t; |
1004 | 0 | timeout.tv_usec = 0; |
1005 | 0 | ret = n = select(h->max_fd_select + 1, &sel_rset, &sel_wset, 0, &timeout); |
1006 | 0 | if(n < 0) { |
1007 | 0 | if(errno == EINTR) |
1008 | 0 | goto again; /* just a signal */ |
1009 | 0 | LM_ERR("select: %s [%d]\n", strerror(errno), errno); |
1010 | 0 | n = 0; |
1011 | | /* continue */ |
1012 | 0 | } |
1013 | | /* use poll fd array */ |
1014 | 0 | for(r = 0; (r < h->fd_no) && n; r++) { |
1015 | 0 | revents = 0; |
1016 | 0 | if(likely(FD_ISSET(h->fd_array[r].fd, &sel_rset))) |
1017 | 0 | revents |= POLLIN; |
1018 | 0 | if(unlikely(FD_ISSET(h->fd_array[r].fd, &sel_wset))) |
1019 | 0 | revents |= POLLOUT; |
1020 | 0 | if(unlikely(revents)) { |
1021 | 0 | h->crt_fd_array_idx = r; |
1022 | 0 | fm = get_fd_map(h, h->fd_array[r].fd); |
1023 | 0 | while(fm->type && (fm->events & revents) |
1024 | 0 | && (handle_io(fm, revents, r) > 0) && repeat) |
1025 | 0 | ; |
1026 | 0 | r = h->crt_fd_array_idx; /* can change due to io_watch_del(fd) |
1027 | | array shifting */ |
1028 | 0 | n--; |
1029 | 0 | } |
1030 | 0 | }; |
1031 | 0 | return ret; |
1032 | 0 | } Unexecuted instantiation: tcp_main.c:io_wait_loop_select Unexecuted instantiation: tcp_read.c:io_wait_loop_select Unexecuted instantiation: io_wait.c:io_wait_loop_select |
1033 | | #endif |
1034 | | |
1035 | | |
1036 | | #ifdef HAVE_EPOLL |
1037 | | inline static int io_wait_loop_epoll(io_wait_h *h, int t, int repeat) |
1038 | 0 | { |
1039 | 0 | int n, r; |
1040 | 0 | struct fd_map *fm; |
1041 | 0 | int revents; |
1042 | |
|
1043 | 0 | again: |
1044 | 0 | n = epoll_wait(h->epfd, h->ep_array, h->fd_no, t * 1000); |
1045 | 0 | if(unlikely(n == -1)) { |
1046 | 0 | if(errno == EINTR) |
1047 | 0 | goto again; /* signal, ignore it */ |
1048 | 0 | else { |
1049 | 0 | LM_ERR("epoll_wait(%d, %p, %d, %d): %s [%d]\n", h->epfd, |
1050 | 0 | h->ep_array, h->fd_no, t * 1000, strerror(errno), errno); |
1051 | 0 | goto error; |
1052 | 0 | } |
1053 | 0 | } |
1054 | | #if 0 |
1055 | | if (n>1){ |
1056 | | for(r=0; r<n; r++){ |
1057 | | LM_ERR("ep_array[%d]= %x, %p\n", |
1058 | | r, h->ep_array[r].events, h->ep_array[r].data.ptr); |
1059 | | } |
1060 | | } |
1061 | | #endif |
1062 | 0 | for(r = 0; r < n; r++) { |
1063 | 0 | revents = |
1064 | 0 | (POLLIN & (!(h->ep_array[r].events & (EPOLLIN | EPOLLPRI)) - 1)) |
1065 | 0 | | (POLLOUT & (!(h->ep_array[r].events & EPOLLOUT) - 1)) |
1066 | 0 | | (POLLERR & (!(h->ep_array[r].events & EPOLLERR) - 1)) |
1067 | 0 | | (POLLHUP & (!(h->ep_array[r].events & EPOLLHUP) - 1)) |
1068 | 0 | #ifdef POLLRDHUP |
1069 | 0 | | (POLLRDHUP & (!(h->ep_array[r].events & EPOLLRDHUP) - 1)) |
1070 | 0 | #endif |
1071 | 0 | ; |
1072 | 0 | if(likely(revents)) { |
1073 | 0 | fm = (struct fd_map *)h->ep_array[r].data.ptr; |
1074 | 0 | while(fm->type && ((fm->events | POLLERR | POLLHUP) & revents) |
1075 | 0 | && (handle_io(fm, revents, -1) > 0) && repeat) |
1076 | 0 | ; |
1077 | 0 | } else { |
1078 | 0 | LM_ERR("unexpected event %x on %d/%d, data=%p\n", |
1079 | 0 | h->ep_array[r].events, r + 1, n, h->ep_array[r].data.ptr); |
1080 | 0 | } |
1081 | 0 | } |
1082 | 0 | error: |
1083 | 0 | return n; |
1084 | 0 | } Unexecuted instantiation: tcp_main.c:io_wait_loop_epoll Unexecuted instantiation: tcp_read.c:io_wait_loop_epoll Unexecuted instantiation: io_wait.c:io_wait_loop_epoll |
1085 | | #endif |
1086 | | |
1087 | | |
1088 | | #ifdef HAVE_KQUEUE |
1089 | | inline static int io_wait_loop_kqueue(io_wait_h *h, int t, int repeat) |
1090 | | { |
1091 | | int n, r; |
1092 | | struct timespec tspec; |
1093 | | struct fd_map *fm; |
1094 | | int orig_changes; |
1095 | | int apply_changes; |
1096 | | int revents; |
1097 | | |
1098 | | tspec.tv_sec = t; |
1099 | | tspec.tv_nsec = 0; |
1100 | | orig_changes = h->kq_nchanges; |
1101 | | apply_changes = orig_changes; |
1102 | | do { |
1103 | | again: |
1104 | | n = kevent(h->kq_fd, h->kq_changes, apply_changes, h->kq_array, |
1105 | | h->kq_array_size, &tspec); |
1106 | | if(unlikely(n == -1)) { |
1107 | | if(unlikely(errno == EINTR)) |
1108 | | goto again; /* signal, ignore it */ |
1109 | | else { |
1110 | | /* for a detailed explanation of what follows see below |
1111 | | the EV_ERROR case */ |
1112 | | if(unlikely(!(errno == EBADF || errno == ENOENT))) |
1113 | | BUG("io_wait_loop_kqueue: kevent: unexpected error" |
1114 | | " %s [%d]\n", |
1115 | | strerror(errno), errno); |
1116 | | /* some of the FDs in kq_changes are bad (already closed) |
1117 | | and there is not enough space in kq_array to return all |
1118 | | of them back */ |
1119 | | apply_changes = h->kq_array_size; |
1120 | | goto again; |
1121 | | } |
1122 | | } |
1123 | | /* remove applied changes */ |
1124 | | h->kq_nchanges -= apply_changes; |
1125 | | if(unlikely(apply_changes < orig_changes)) { |
1126 | | orig_changes -= apply_changes; |
1127 | | memmove(&h->kq_changes[0], &h->kq_changes[apply_changes], |
1128 | | sizeof(h->kq_changes[0]) * h->kq_nchanges); |
1129 | | apply_changes = (orig_changes < h->kq_array_size) |
1130 | | ? orig_changes |
1131 | | : h->kq_array_size; |
1132 | | } else { |
1133 | | orig_changes = 0; |
1134 | | apply_changes = 0; |
1135 | | } |
1136 | | for(r = 0; r < n; r++) { |
1137 | | #ifdef EXTRA_DEBUG |
1138 | | DBG("DBG: kqueue: event %d/%d: fd=%d, udata=%lx, flags=0x%x\n", r, |
1139 | | n, h->kq_array[r].ident, (long)h->kq_array[r].udata, |
1140 | | h->kq_array[r].flags); |
1141 | | #endif |
1142 | | if(unlikely((h->kq_array[r].flags & EV_ERROR) |
1143 | | || h->kq_array[r].udata == 0)) { |
1144 | | /* error in changes: we ignore it if it has to do with a |
1145 | | bad fd or update==0. It can be caused by trying to remove an |
1146 | | already closed fd: race between adding something to the |
1147 | | changes array, close() and applying the changes (EBADF). |
1148 | | E.g. for ser tcp: tcp_main sends a fd to child for reading |
1149 | | => deletes it from the watched fds => the changes array |
1150 | | will contain an EV_DELETE for it. Before the changes |
1151 | | are applied (they are at the end of the main io_wait loop, |
1152 | | after all the fd events were processed), a CON_ERR sent |
1153 | | to tcp_main by a sender (send fail) is processed and causes |
1154 | | the fd to be closed. When the changes are applied => |
1155 | | error for the EV_DELETE attempt of a closed fd. |
1156 | | Something similar can happen when a fd is scheduled |
1157 | | for removal, is close()'ed before being removed and |
1158 | | re-opened(a new sock. get the same fd). When the |
1159 | | watched fd changes will be applied the fd will be valid |
1160 | | (so no EBADF), but it's not already watch => ENOENT. |
1161 | | We report a BUG for the other errors (there's nothing |
1162 | | constructive we can do if we get an error we don't know |
1163 | | how to handle), but apart from that we ignore it in the |
1164 | | idea that it is better apply the rest of the changes, |
1165 | | rather than dropping all of them. |
1166 | | */ |
1167 | | /* |
1168 | | example EV_ERROR for trying to delete a read watched fd, |
1169 | | that was already closed: |
1170 | | { |
1171 | | ident = 63, [fd] |
1172 | | filter = -1, [EVFILT_READ] |
1173 | | flags = 16384, [EV_ERROR] |
1174 | | fflags = 0, |
1175 | | data = 9, [errno = EBADF] |
1176 | | udata = 0x0 |
1177 | | } |
1178 | | */ |
1179 | | if(h->kq_array[r].data != EBADF |
1180 | | && h->kq_array[r].data != ENOENT) |
1181 | | BUG("io_wait_loop_kqueue: kevent unexpected error on " |
1182 | | "fd %ld udata %lx: %s [%ld]\n", |
1183 | | (long)h->kq_array[r].ident, |
1184 | | (long)h->kq_array[r].udata, |
1185 | | strerror(h->kq_array[r].data), |
1186 | | (long)h->kq_array[r].data); |
1187 | | } else { |
1188 | | fm = (struct fd_map *)h->kq_array[r].udata; |
1189 | | if(likely(h->kq_array[r].filter == EVFILT_READ)) { |
1190 | | revents = POLLIN |
1191 | | | (((int)!(h->kq_array[r].flags & EV_EOF) - 1) |
1192 | | & POLLHUP) |
1193 | | | (((int)!((h->kq_array[r].flags & EV_EOF) |
1194 | | && h->kq_array[r].fflags != 0) |
1195 | | - 1) |
1196 | | & POLLERR); |
1197 | | while(fm->type && (fm->events & revents) |
1198 | | && (handle_io(fm, revents, -1) > 0) && repeat) |
1199 | | ; |
1200 | | } else if(h->kq_array[r].filter == EVFILT_WRITE) { |
1201 | | revents = POLLOUT |
1202 | | | (((int)!(h->kq_array[r].flags & EV_EOF) - 1) |
1203 | | & POLLHUP) |
1204 | | | (((int)!((h->kq_array[r].flags & EV_EOF) |
1205 | | && h->kq_array[r].fflags != 0) |
1206 | | - 1) |
1207 | | & POLLERR); |
1208 | | while(fm->type && (fm->events & revents) |
1209 | | && (handle_io(fm, revents, -1) > 0) && repeat) |
1210 | | ; |
1211 | | } else { |
1212 | | BUG("io_wait_loop_kqueue: unknown filter: kqueue: event " |
1213 | | "%d/%d: fd=%d, filter=%d, flags=0x%x, fflags=0x%x," |
1214 | | " data=%lx, udata=%lx\n", |
1215 | | r, n, (int)h->kq_array[r].ident, |
1216 | | (int)h->kq_array[r].filter, h->kq_array[r].flags, |
1217 | | h->kq_array[r].fflags, |
1218 | | (unsigned long)h->kq_array[r].data, |
1219 | | (unsigned long)h->kq_array[r].udata); |
1220 | | } |
1221 | | } |
1222 | | } |
1223 | | } while(unlikely(orig_changes)); |
1224 | | return n; |
1225 | | } |
1226 | | #endif |
1227 | | |
1228 | | |
1229 | | #ifdef HAVE_SIGIO_RT |
1230 | | /* sigio rt version has no repeat (it doesn't make sense)*/ |
1231 | | inline static int io_wait_loop_sigio_rt(io_wait_h *h, int t) |
1232 | 0 | { |
1233 | 0 | int n; |
1234 | 0 | int ret; |
1235 | 0 | struct timespec ts; |
1236 | 0 | siginfo_t siginfo; |
1237 | 0 | int sigio_band; |
1238 | 0 | int sigio_fd; |
1239 | 0 | struct fd_map *fm; |
1240 | 0 | int revents; |
1241 | 0 | #ifdef SIGINFO64_WORKAROUND |
1242 | 0 | int *pi; |
1243 | 0 | #endif |
1244 | | |
1245 | |
|
1246 | 0 | ret = 1; /* 1 event per call normally */ |
1247 | 0 | ts.tv_sec = t; |
1248 | 0 | ts.tv_nsec = 0; |
1249 | 0 | if(unlikely(!sigismember(&h->sset, h->signo) |
1250 | 0 | || !sigismember(&h->sset, SIGIO))) { |
1251 | 0 | LM_CRIT("the signal mask is not properly set!\n"); |
1252 | 0 | goto error; |
1253 | 0 | } |
1254 | 0 | again: |
1255 | 0 | n = sigtimedwait(&h->sset, &siginfo, &ts); |
1256 | 0 | if(unlikely(n == -1)) { |
1257 | 0 | if(errno == EINTR) |
1258 | 0 | goto again; /* some other signal, ignore it */ |
1259 | 0 | else if(errno == EAGAIN) { /* timeout */ |
1260 | 0 | ret = 0; |
1261 | 0 | goto end; |
1262 | 0 | } else { |
1263 | 0 | LM_ERR("sigtimed_wait %s [%d]\n", strerror(errno), errno); |
1264 | 0 | goto error; |
1265 | 0 | } |
1266 | 0 | } |
1267 | 0 | if(likely(n != SIGIO)) { |
1268 | 0 | #ifdef SIGINFO64_WORKAROUND |
1269 | | /* on linux siginfo.si_band is defined as long in userspace |
1270 | | * and as int in kernel (< 2.6.5) => on 64 bits things will break! |
1271 | | * (si_band will include si_fd, and si_fd will contain |
1272 | | * garbage). |
1273 | | * see /usr/src/linux/include/asm-generic/siginfo.h and |
1274 | | * /usr/include/bits/siginfo.h |
1275 | | * On newer kernels this is fixed (si_band is long in the kernel too). |
1276 | | * -- andrei */ |
1277 | 0 | if((_os_ver < 0x020605) && (sizeof(siginfo.si_band) > sizeof(int))) { |
1278 | 0 | pi = (int *)(void *)&siginfo |
1279 | 0 | .si_band; /* avoid type punning warnings */ |
1280 | 0 | sigio_band = *pi; |
1281 | 0 | sigio_fd = *(pi + 1); |
1282 | 0 | } else |
1283 | 0 | #endif |
1284 | 0 | { |
1285 | 0 | sigio_band = siginfo.si_band; |
1286 | 0 | sigio_fd = siginfo.si_fd; |
1287 | 0 | } |
1288 | 0 | if(unlikely(siginfo.si_code == SI_SIGIO)) { |
1289 | | /* old style, we don't know the event (linux 2.2.?) */ |
1290 | 0 | LM_WARN("old style sigio interface\n"); |
1291 | 0 | fm = get_fd_map(h, sigio_fd); |
1292 | | /* we can have queued signals generated by fds not watched |
1293 | | * any more, or by fds in transition, to a child => ignore them*/ |
1294 | 0 | if(fm->type) |
1295 | 0 | handle_io(fm, POLLIN | POLLOUT, -1); |
1296 | 0 | } else { |
1297 | | /* si_code contains the SIGPOLL reason: POLL_IN, POLL_OUT, |
1298 | | * POLL_MSG, POLL_ERR, POLL_PRI or POLL_HUP |
1299 | | * and si_band the translated poll event bitmap: |
1300 | | * POLLIN|POLLRDNORM (=POLL_IN), |
1301 | | * POLLOUT|POLLWRNORM|POLLWRBAND (=POLL_OUT), |
1302 | | * POLLIN|POLLRDNORM|POLLMSG (=POLL_MSG), |
1303 | | * POLLERR (=POLL_ERR), |
1304 | | * POLLPRI|POLLRDBAND (=POLL_PRI), |
1305 | | * POLLHUP|POLLERR (=POLL_HUP) |
1306 | | * [linux 2.6.22 fs/fcntl.c:447] |
1307 | | */ |
1308 | | #ifdef EXTRA_DEBUG |
1309 | | DBG("io_wait_loop_sigio_rt: siginfo: signal=%d (%d)," |
1310 | | " si_code=%d, si_band=0x%x," |
1311 | | " si_fd=%d\n", |
1312 | | siginfo.si_signo, n, siginfo.si_code, (unsigned)sigio_band, |
1313 | | sigio_fd); |
1314 | | #endif |
1315 | | /* on some errors (e.g. when receiving TCP RST), sigio_band will |
1316 | | * be set to 0x08 (POLLERR) or 0x18 (POLLERR|POLLHUP - on stream |
1317 | | * unix socket close) , so better catch all events --andrei */ |
1318 | 0 | if(likely(sigio_band)) { |
1319 | 0 | fm = get_fd_map(h, sigio_fd); |
1320 | 0 | revents = sigio_band; |
1321 | | /* fix revents==POLLPRI case */ |
1322 | 0 | revents |= (!(revents & POLLPRI) - 1) & POLLIN; |
1323 | | /* we can have queued signals generated by fds not watched |
1324 | | * any more, or by fds in transition, to a child |
1325 | | * => ignore them */ |
1326 | 0 | if(fm->type && ((fm->events | POLLERR | POLLHUP) & revents)) |
1327 | 0 | handle_io(fm, revents, -1); |
1328 | 0 | else |
1329 | 0 | DBG("WARNING: io_wait_loop_sigio_rt: ignoring event" |
1330 | 0 | " %x on fd %d, watching for %x, si_code=%x " |
1331 | 0 | "(fm->type=%d, fm->fd=%d, fm->data=%p)\n", |
1332 | 0 | sigio_band, sigio_fd, fm->events, siginfo.si_code, |
1333 | 0 | fm->type, fm->fd, fm->data); |
1334 | 0 | } else { |
1335 | 0 | LM_ERR("unexpected event on fd %d: %x\n", sigio_fd, sigio_band); |
1336 | 0 | } |
1337 | 0 | } |
1338 | 0 | } else { |
1339 | | /* signal queue overflow |
1340 | | * TODO: increase signal queue size: 2.4x /proc/.., 2.6x -rlimits */ |
1341 | 0 | LM_WARN("signal queue overflowed - falling back to poll\n"); |
1342 | | /* clear real-time signal queue |
1343 | | * both SIG_IGN and SIG_DFL are needed , it doesn't work |
1344 | | * only with SIG_DFL */ |
1345 | 0 | if(signal(h->signo, SIG_IGN) == SIG_ERR) { |
1346 | 0 | LM_CRIT("do_poll: couldn't reset signal to IGN\n"); |
1347 | 0 | } |
1348 | |
|
1349 | 0 | if(signal(h->signo, SIG_DFL) == SIG_ERR) { |
1350 | 0 | LM_CRIT("do_poll: couldn't reset signal to DFL\n"); |
1351 | 0 | } |
1352 | | /* falling back to normal poll */ |
1353 | 0 | ret = io_wait_loop_poll(h, -1, 1); |
1354 | 0 | } |
1355 | 0 | end: |
1356 | 0 | return ret; |
1357 | 0 | error: |
1358 | 0 | return -1; |
1359 | 0 | } Unexecuted instantiation: tcp_main.c:io_wait_loop_sigio_rt Unexecuted instantiation: tcp_read.c:io_wait_loop_sigio_rt Unexecuted instantiation: io_wait.c:io_wait_loop_sigio_rt |
1360 | | #endif |
1361 | | |
1362 | | |
1363 | | #ifdef HAVE_DEVPOLL |
1364 | | inline static int io_wait_loop_devpoll(io_wait_h *h, int t, int repeat) |
1365 | | { |
1366 | | int n, r; |
1367 | | int ret; |
1368 | | struct dvpoll dpoll; |
1369 | | struct fd_map *fm; |
1370 | | |
1371 | | dpoll.dp_timeout = t * 1000; |
1372 | | dpoll.dp_nfds = h->fd_no; |
1373 | | dpoll.dp_fds = h->fd_array; |
1374 | | again: |
1375 | | ret = n = ioctl(h->dpoll_fd, DP_POLL, &dpoll); |
1376 | | if(unlikely(n == -1)) { |
1377 | | if(errno == EINTR) |
1378 | | goto again; /* signal, ignore it */ |
1379 | | else { |
1380 | | LM_ERR("ioctl: %s [%d]\n", strerror(errno), errno); |
1381 | | goto error; |
1382 | | } |
1383 | | } |
1384 | | for(r = 0; r < n; r++) { |
1385 | | if(h->fd_array[r].revents & (POLLNVAL | POLLERR)) { |
1386 | | LM_ERR("pollinval returned for fd %d, revents=%x\n", |
1387 | | h->fd_array[r].fd, h->fd_array[r].revents); |
1388 | | } |
1389 | | /* POLLIN|POLLHUP just go through */ |
1390 | | fm = get_fd_map(h, h->fd_array[r].fd); |
1391 | | while(fm->type && (fm->events & h->fd_array[r].revents) |
1392 | | && (handle_io(fm, h->fd_array[r].revents, r) > 0) && repeat) |
1393 | | ; |
1394 | | } |
1395 | | error: |
1396 | | return ret; |
1397 | | } |
1398 | | #endif |
1399 | | |
1400 | | |
1401 | | /* init */ |
1402 | | |
1403 | | |
1404 | | /* initializes the static vars/arrays |
1405 | | * params: h - pointer to the io_wait_h that will be initialized |
1406 | | * max_fd - maximum allowed fd number |
1407 | | * poll_m - poll method (0 for automatic best fit) |
1408 | | */ |
1409 | | int init_io_wait(io_wait_h *h, int max_fd, enum poll_types poll_method); |
1410 | | |
1411 | | /* destroys everything init_io_wait allocated */ |
1412 | | void destroy_io_wait(io_wait_h *h); |
1413 | | |
1414 | | |
1415 | | #endif |