views:

306

answers:

4

i.e.

  1. open a listening socket in parent process
  2. call epoll_wait(listening_socket) in child1,child2,child3....
  3. call accept in each child if there is connection request
A: 

Your question isn't formulated precisely, but I believe that you can find your answer here:

Kornel Kisielewicz
+2  A: 

In general, it's not a good idea to have multiple threads performing IO on the same socket without some kind of synchronization between them. In your scenario, it's possible you'd see something like:

  • incoming connection request wakes up epoll_wait in all N child threads
  • all N threads call accept, 1 call succeeds, N-1 block (or fail, if your listening socket is non-blocking)

The more usual approach is to have the parent thread loop calling accept on the listening socket, and starting a child thread for each incoming request. (Or, if you're concerned about thread creation overhead, you can have a pool of child threads that wait on a condition variable when idle; the parent adds the newly-accepted socket to a queue and uses pthread_cond_signal to wake a child to handle it.)

David Gelhar
More acurately, you should not have multiple threads performing the SAME KIND OF IO on a socket at the same time. You can have one thread reading from the socket while another thread is writing to the same socket, and that is perfectly safe. But you cannot have two or more threads reading at the same time, or writing at the same time, or listening at the same time, without synchronizing them.
Remy Lebeau - TeamB
A: 

hi there:

the scenario basically is from nginx,I don't know if it has some extra mechanisms to avoid "thundering herd" problem.

I did observe that not all childs receive epoll event when I send a http request via IE. so that only one child will call "accept" eventually

//jon

jon
I don't think you should depend on only one child receiving epoll event. The epoll man page says "Q2 Can two epoll sets wait for the same fd? If so, are events reported to both epoll sets fds?" "A2 Yes. However, it is not recommended. Yes it would be reported to both."
David Gelhar
Registering the same fd to two epoll sets (pay attention to the word *sets* here) would result in the events of that fd being reported to both epoll sets.Registering the fd in a single epoll set and calling epoll_wait in that set from within different child threads is completely safe.
Horacio
+1  A: 

Yes you can but your example is a little incomplete:

  1. Create listening_socket
  2. Create epoll set using *epoll_create*
  3. Register listening_socket to the epoll set using *epoll_ctl*
  4. call *epoll_wait*(epoll set) in child1,child2,child3....
  5. call accept in each child if there is connection request

epoll_wait makes sures that only one thread gets the connection event and only that thread will call accept.

If you create two epoll sets and register your listening_socket to both of them you will receive the event twice, once per epoll set, and this is not recommended.

You may refer to this tutorial http://www.devshed.com/c/a/BrainDump/Linux-Files-and-the-Event-Poll-Interface/ and search some interesting discussions about epoll in this forum http://www.developerweb.net/forum/ to learn more.

For more elaborate examples you can always refer to the libev, libevent or nginx source code.

Horacio