solofarm
solofarm

Reputation: 1

Tcp client with epoll on linux. EPOLLIN event not rised with multiple connections

Have a problem with recieveing data via epoll from answers in client app.

I'v made a simple illustration code. Ommited maximum error-handling logic.

Short context description:

  1. client app creates 2 nonblocking sockets(SOCK_NON_BLOCK passed to socket and not via fcntl)
  2. client add sockets to events with EPOLLOUT | EPOLLONESHOT and calls connect on each socket(non blocking so i get EINPROGRESS) client waits with epoll_wait for connection established (wait for EPOLLOUT)
  3. when conected - sends 1 packet request(for illustration i made HEAD requests with example.com host to google.com servers)
  4. when sent returns epoll notify filters switched to EPOLLIN
  5. client waits for data to read (if not EAGAIN) and closes the socket after first chunk readed(its ok)

Problem:

only one socket gets nitification that answer has come.

In tcpdump i see that web servers send both answers( Here is tcpdump with highlighted both answers from servers. So both request passed and answers has come http://pastie.org/10504786#59-78,89-109 )

I'v prepared maximum simple example with two hardcoded google ips (for simplicity to skip name resolv).

Seems code is a bit huge for post, so example here: http://pastie.org/10504718

Here is compile and output:

% gcc -std=c99 -Wall ./main.c && ./a.out
assigned 4 for 173.194.32.135
assigned 5 for 173.194.32.130
socket 4
  write event
  data send 35 via 4
socket 5
  write event
  data send 35 via 5
socket 5
  read event
  read returned 258  <-- we have answer from first
socket 5
  read event
  read returned 4294967295 
  read errno =9 errmesg= Bad file descriptor <--its ok cause we closed fd,but seems its event cached event 

One cat see 2 connections established, and two requests sent, but read event fired for only for one socket.

Can't get what is the case of such behaviour, socket configuration seems to be independent.

Upvotes: 0

Views: 2679

Answers (1)

solofarm
solofarm

Reputation: 1

Shame on me.

The error was in wrong event data initialization. I forgot to reassign pointer do associated struct, when switching to IN. So all switches were pointing to the same data.

error code

    //switching data listen
    ev.events = EPOLLIN | EPOLLONESHOT;
    epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev);

(http://pastie.org/10504718#83-85)

should be

    //switching data listen
    ev.data.ptr = c;
    ev.events = EPOLLIN | EPOLLONESHOT;
    epoll_ctl(epfd, EPOLL_CTL_MOD, c->fd, &ev);

Upvotes: 0

Related Questions