不同线程中的几个epoll_wait接收不是为它们设计的事件

时间:2011-12-15 04:46:20

标签: c linux sockets

我有两次event_wait调用 线程1:来自子进程的侦听管道

        struct epoll_event *ev;
        struct EpollStub stub[pool->plugins.count];
...
        epollfd = epoll_create1(0);
        if (epollfd == -1) {
                return -1;
        }
        ev->events = EPOLLIN;
        for(int i=0;i<plugins->count;i++) {
             inf = &plugins->stp[i];
             stub[i].type = EREAD_STAP;
             stub[i].pointer = inf;
             ev->data.ptr = stub+i;
             if (epoll_ctl(pool->epollfd, EPOLL_CTL_ADD, inf->fd, ev) == -1) {
                 close(epollfd);
                 return -1;
             }
        }
        do {
            n = epoll_wait(pool->epollfd, evs, EPOLL_EVENTS_MAX, -1);
            for(int i=0;i<n;i++) {
                ev = evs + i;
                struct EpollStub *stub = (struct EpollStub *)ev->data.ptr;
                if(stub->type!=EREAD_STAP) {
                    #ifdef __MDEBUG
                    printf("EREAD: Wrong event: %d\n",stub->type);
                    #endif
                    continue;
                }
                else {
    //            inf = (struct StpInfo*)ev->data.ptr;
                    inf = (struct StpInfo*)stub->pointer;
                    fd = inf->fd;
                    #ifdef __MDEBUG
                    printf("EREAD fd: %d\n",fd);
                    #endif
///do something here
                    } 
    ....

主题2:倾听客户端套接字

    struct epoll_event ev;
    pool->epollfd = epoll_create1(0);
    if (pool->epollfd == -1) {
       return -1;
    }
    ev.events = EPOLLIN;
    for(int i=0;i<pool->sockets.count;i++) {
        struct EpollStub *stub = &pool->sockets.stub[i];
        stub->type = EACCEPT_CONN;
        stub->pointer = pool->sockets.fd[i];
        ev.data.ptr = stub;
        if (epoll_ctl(pool->epollfd, EPOLL_CTL_ADD, (int)stub->pointer, &ev) = -1) {
             return -1;
       }
    }
...

    cfd = epoll_wait(pool->epollfd, &ev, 1, -1);
    if(is_working(pool,cfd)) {
        struct EpollStub *stub = (struct EpollStub *)ev.data.ptr;
        if(stub->type!=EACCEPT_CONN) {
            #ifdef __MDEBUG
            printf("EACCEPT: Wrong event: %d\n",stub->type);
            #endif
        }
        else {
            #ifdef __MDEBUG
            printf("EACCEPT fd: %d\n",(int)stub->pointer);
            #endif
            break;
///do something here
        }
    }
    ....

kernel:opensuse-3.1.0-1.2-desktop
他们互相得到了一些事件。我让EpollStub只是因为他们得到了保姆。如果没有这个第一个事件,则返回指针第二个句柄,结果是接收描述符时的分段错误并将其用作指针。
我认为这不是正常行为。这是内核中的错误或我错在哪里?

1 个答案:

答案 0 :(得分:1)

这是您代码中的错误。您在一些地方混淆了pool->epollfdepollfd,例如:

    epollfd = epoll_create1(0);
    if (epollfd == -1) {
            return -1;
    }
    ev->events = EPOLLIN;
    for(int i=0;i<plugins->count;i++) {
         inf = &plugins->stp[i];
         stub[i].type = EREAD_STAP;
         stub[i].pointer = inf;
         ev->data.ptr = stub+i;
         if (epoll_ctl(pool->epollfd, EPOLL_CTL_ADD, inf->fd, ev) == -1) {
             close(epollfd);
             return -1;
         }
    }
    do {
        n = epoll_wait(pool->epollfd, evs, EPOLL_EVENTS_MAX, -1);

您创建epollfd,但随后修改pool->epollfd并等待。如果您有两个不同的事件集,则需要使用两个不同的epoll fds。

epoll机制完全与线程无关。它不会将事件或集绑定到线程。任何线程都可以在集合中添加或删除描述符。任何线程都可以为任何集合获取事件。