2011-12-15 3 views
0

私はevent_waitを2回呼び出します。
スレッド1:リスニングクライアントソケット
異なるスレッドのいくつかのepoll_waitは、それらには関係のないイベントを受け取ります

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 
     } 
    } 
    .... 

カーネル:openSUSEの-3.1.0-1.2-デスクトップ
子供から聞くパイプが

 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を処理します 彼らはお互いからイベントを取得します。私はEpollStubを彼らが得意とするだけのものにしました。この最初のイベントがなければ、ポインタが2番目のハンドルを返し、その結果がディスクリプタを受け取ってポインタとして使用すると、セグメンテーション違反になります。
これは正常な動作ではないと思います。これはカーネルのバグですか、どこが間違っていますか?

答えて

1

これはコードのバグです。次の例のように、いくつかの場所でepollfdpool->epollfd混同しています

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を変更し、その上で待機します。 2つの異なるイベントセットがある場合は、2つの異なるepollファイルを使用する必要があります。

epollメカニズムは完全にスレッドに依存しません。イベントやセットをスレッドにバインドしません。任意のスレッドは、ディスクリプタをセットに追加またはディスクセットから削除することができます。どのスレッドも任意のセットのイベントを取得できます。

+0

ありがとうございます。私はすでに気づいている。ちょうど愚かなタイプミス。 – user1099086

関連する問題