Example #1
0
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;
	}
}
Example #2
0
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;
}
Example #4
0
/*
  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);
}
Example #5
0
/*
  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);
}
Example #7
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;
}
Example #8
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;
}