static void epoll_change_event(struct std_event_context *std_ev, struct tevent_fd *fde) { bool got_error = (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR); bool want_read = (fde->flags & TEVENT_FD_READ); bool want_write= (fde->flags & TEVENT_FD_WRITE); if (std_ev->epoll_fd == -1) return; fde->additional_flags &= ~EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR; /* there's already an event */ if (fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_HAS_EVENT) { if (want_read || (want_write && !got_error)) { epoll_mod_event(std_ev, fde); return; } /* * if we want to match the select behavior, we need to remove the epoll_event * when the caller isn't interested in events. * * this is because epoll reports EPOLLERR and EPOLLHUP, even without asking for them */ epoll_del_event(std_ev, fde); return; } /* there's no epoll_event attached to the fde */ if (want_read || (want_write && !got_error)) { epoll_add_event(std_ev, fde); return; } }
void Server::CloseClient(int id){ int fd = clients[id].fd; char msg[256] = {0}; printf("id %d fd %d\n", id, clients[id].fd); sprintf(msg, "*** User '%s' left. ***\n", clients[id].nickname); SendAll(msg); clients[id].used = false; client_id.erase(id); epoll_del_event(epfd, fd, EPOLLIN); int res = close(fd); printf("close %d %d\n", id, res); }
int on_close(int epoll_fd, int fd) { std::map<int, socket_buf>::iterator it = sb_array.begin(); epoll_del_event(epoll_fd, fd); printf("debug: start free %d\n", fd); if((it = sb_array.find(fd)) != sb_array.end()) sb_array.erase(sb_array.find(fd)); free_socket_buf(fd); close(fd); return L_HTTP_SUCCESS; }
/* destroy an fd_event */ static int epoll_event_fd_destructor(struct tevent_fd *fde) { struct tevent_context *ev = fde->event_ctx; struct epoll_event_context *epoll_ev = NULL; if (ev) { epoll_ev = talloc_get_type(ev->additional_data, struct epoll_event_context); epoll_check_reopen(epoll_ev); epoll_del_event(epoll_ev, fde); } return tevent_common_fd_destructor(fde); }
/* destroy an fd_event */ static int std_event_fd_destructor(struct tevent_fd *fde) { struct tevent_context *ev = fde->event_ctx; struct std_event_context *std_ev = NULL; if (ev) { std_ev = talloc_get_type(ev->additional_data, struct std_event_context); epoll_check_reopen(std_ev); if (std_ev->maxfd == fde->fd) { std_ev->maxfd = EVENT_INVALID_MAXFD; } epoll_del_event(std_ev, fde); } return tevent_common_fd_destructor(fde); }
void worker_shutdown(int epoll_fd) { // shutdown all the connection std::map<int, socket_buf>::iterator it = sb_array.begin(); int fd = -1; for(; it != sb_array.end(); it++) { fd = it->first; if(fd == -1) continue; epoll_del_event(epoll_fd, fd); printf("debug: start free %d\n", fd); sb_array.erase(sb_array.find(fd)); free_socket_buf(it->second); close(fd); } exit(0); }
/* event loop handling using epoll */ static int epoll_event_loop(struct std_event_context *std_ev, struct timeval *tvalp) { int ret, i; #define MAXEVENTS 1 struct epoll_event events[MAXEVENTS]; int timeout = -1; if (std_ev->epoll_fd == -1) return -1; if (tvalp) { /* it's better to trigger timed events a bit later than to early */ timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000); } if (std_ev->ev->signal_events && tevent_common_check_signal(std_ev->ev)) { return 0; } ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout); if (ret == -1 && errno == EINTR && std_ev->ev->signal_events) { if (tevent_common_check_signal(std_ev->ev)) { return 0; } } if (ret == -1 && errno != EINTR) { epoll_fallback_to_select(std_ev, "epoll_wait() failed"); return -1; } if (ret == 0 && tvalp) { /* we don't care about a possible delay here */ tevent_common_loop_timer_delay(std_ev->ev); return 0; } for (i=0;i<ret;i++) { struct tevent_fd *fde = talloc_get_type(events[i].data.ptr, struct tevent_fd); uint16_t flags = 0; if (fde == NULL) { epoll_fallback_to_select(std_ev, "epoll_wait() gave bad data"); return -1; } if (events[i].events & (EPOLLHUP|EPOLLERR)) { fde->additional_flags |= EPOLL_ADDITIONAL_FD_FLAG_GOT_ERROR; /* * if we only wait for TEVENT_FD_WRITE, we should not tell the * event handler about it, and remove the epoll_event, * as we only report errors when waiting for read events, * to match the select() behavior */ if (!(fde->additional_flags & EPOLL_ADDITIONAL_FD_FLAG_REPORT_ERROR)) { epoll_del_event(std_ev, fde); continue; } flags |= TEVENT_FD_READ; } if (events[i].events & EPOLLIN) flags |= TEVENT_FD_READ; if (events[i].events & EPOLLOUT) flags |= TEVENT_FD_WRITE; if (flags) { fde->handler(std_ev->ev, fde, flags, fde->private_data); break; } } return 0; }
int epoll_process_events(int timer) { int rslt = HIXO_OK; int nevents = 0; int tmp_err = 0; hixo_conf_t *p_conf = g_rt_ctx.mp_conf; if ((gp_ps_info->m_power > 0) && spinlock_try(g_rt_ctx.mp_accept_lock)) { s_epoll_private.m_hold_lock = TRUE; } else { s_epoll_private.m_hold_lock = FALSE; } // 添加监听套接字事件监视 if (s_epoll_private.m_hold_lock) { for (int i = 0; i < g_rt_ctx.m_nservers; ++i) { assert(0 == (((uintptr_t)g_rt_ctx.mpp_servers[i]) & 1)); if (HIXO_ERROR == epoll_add_event(g_rt_ctx.mpp_servers[i])) { g_rt_ctx.mpp_servers[i] = (hixo_socket_t *)( ((uintptr_t)g_rt_ctx.mpp_servers[i]) | 1 ); break; } } } assert(NULL == g_rt_ctx.mp_posted_events); errno = 0; nevents = epoll_wait(s_epoll_private.m_epfd, s_epoll_private.mp_epevs, p_conf->m_max_connections, timer); tmp_err = errno; // 清除监听套接字事件监视 if (s_epoll_private.m_hold_lock) { for (int i = 0; i < g_rt_ctx.m_nservers; ++i) { if (((uintptr_t)g_rt_ctx.mpp_servers[i]) & 1) { g_rt_ctx.mpp_servers[i] = (hixo_socket_t *)( ((uintptr_t)g_rt_ctx.mpp_servers[i]) & (~1) ); continue; } if (HIXO_ERROR == epoll_del_event(g_rt_ctx.mpp_servers[i])) { break; } } } if (tmp_err) { if (EINTR == tmp_err) { (void)fprintf(stderr, "[INFO] epoll_wait interupted\n"); goto EXIT; } else { rslt = HIXO_ERROR; (void)fprintf(stderr, "[ERROR] epoll_wait failed: %d\n", tmp_err); goto EXIT; } } if (0 == nevents) { // timeout goto EXIT; } // 处理事件 for (int i = 0; i < nevents; ++i) { struct epoll_event *p_epev = &s_epoll_private.mp_epevs[i]; uintptr_t stale = ((uintptr_t)p_epev->data.ptr) & 1; hixo_socket_t *p_sock = (hixo_socket_t *)((uintptr_t)p_epev->data.ptr & (~1)); if ((-1 == p_sock->m_fd) || (stale != p_sock->m_stale)) { continue; } if ((HIXO_EVENT_ERR | HIXO_EVENT_HUP) & p_epev->events) { p_epev->events |= HIXO_EVENT_IN | HIXO_EVENT_OUT; } p_sock->m_readable = (HIXO_EVENT_IN & p_epev->events) ? 1U : 0U; p_sock->m_writable = (HIXO_EVENT_OUT & p_epev->events) ? 1U : 0U; if (p_sock->m_writable || p_sock->m_readable) { add_node(&g_rt_ctx.mp_posted_events, &p_sock->m_posted_node); } } EXIT: if (s_epoll_private.m_hold_lock) { // 只有拿到锁的进程才能解锁 (void)spinlock_unlock(g_rt_ctx.mp_accept_lock); s_epoll_private.m_hold_lock = FALSE; } return rslt; }