| 167 | |
| 168 | #ifdef HAVE_EPOLL |
| 169 | inline static int io_wait_loop_epoll(io_wait_h* h, int t, int repeat) |
| 170 | { |
| 171 | int ret, n, r, i; |
| 172 | struct fd_map *e; |
| 173 | struct epoll_event ep_event; |
| 174 | int fd; |
| 175 | unsigned int curr_time; |
| 176 | |
| 177 | again: |
| 178 | ret=n=epoll_wait(h->epfd, h->ep_array, h->fd_no, t*1000); |
| 179 | if (n==-1){ |
| 180 | if (errno == EINTR) { |
| 181 | goto again; /* signal, ignore it */ |
| 182 | } else if (h->fd_no == 0) { |
| 183 | sleep(t); |
| 184 | return 0; |
| 185 | } else { |
| 186 | LM_ERR("[%s] epoll_wait(%d, %p, %d, %d): %s [%d]\n", |
| 187 | h->name,h->epfd, h->ep_array, h->fd_no, t*1000, |
| 188 | strerror(errno), errno); |
| 189 | goto error; |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | curr_time = get_ticks(); |
| 194 | |
| 195 | for (r=0; r<n; r++) { |
| 196 | #if 0 |
| 197 | LM_NOTICE("[%s] triggering fd %d, events %d, flags %d\n", |
| 198 | h->name, ((struct fd_map*)h->ep_array[r].data.ptr)->fd, |
| 199 | h->ep_array[r].events, |
| 200 | ((struct fd_map*)h->ep_array[r].data.ptr)->flags); |
| 201 | #endif |
| 202 | /* do some sanity check over the triggered fd */ |
| 203 | e = ((struct fd_map*)h->ep_array[r].data.ptr); |
| 204 | if (e->type==0 || e->fd<=0 || |
| 205 | (e->flags&(IO_WATCH_READ|IO_WATCH_WRITE))==0 ) { |
| 206 | fd = e - h->fd_hash; |
| 207 | LM_ERR("[%s] unset/bogus map (idx=%d) triggered for %d by " |
| 208 | "epoll (fd=%d,type=%d,flags=%x,data=%p) -> removing " |
| 209 | "from epoll\n", h->name, |
| 210 | fd, h->ep_array[r].events, |
| 211 | e->fd, e->type, e->flags, e->data); |
| 212 | /* as the triggering fd has no corresponding in fd_map, better |
| 213 | * remove it from poll, to avoid un-managed reporting |
| 214 | * on this fd */ |
| 215 | if (epoll_ctl(h->epfd, EPOLL_CTL_DEL, fd, &ep_event)<0) { |
| 216 | LM_ERR("failed to remove from epoll %s(%d)\n", |
| 217 | strerror(errno), errno); |
| 218 | } |
| 219 | close(fd); |
| 220 | continue; |
| 221 | } |
| 222 | |
| 223 | /* anything containing EPOLLIN (like HUP or ERR) goes as a READ */ |
| 224 | if (h->ep_array[r].events & EPOLLIN) { |
| 225 | if ((e->flags&IO_WATCH_READ)==0) { |
| 226 | LM_BUG("[%s] EPOLLIN triggered(%d) for non-read fd_map " |