Q:

Problems with epoll and socket accept in forked children

I have a little server/client script written in Python.
The server.py creates a new socket and spawns two children.
in child process I register the socket des criptor for EPOLLIN event, so
I can do an accept on socket in the child. The problem is, that both children are 
being notificated on client request, BUT only one child does the accept, and the other one
is throwing an Exception "[Errno 11] Resource temporarily unavailable". 
HOW can I prevent ALL children from getting notification, if they are not able to do an accept on socket?
---server.py---
import socket, time, os, select

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('127.0.0.1', 10000))
sock.listen(256)
sock.setblocking(False)

for _ in range(0,2):

    pid = os.fork()
    if pid == 0:    #in child
        poll = select.epoll()
        poll.register(sock.fileno(), select.EPOLLIN)
        while True:
            events = poll.poll(2)   # listening for events with 2 sec timeout
            for fileno, event in events:
                if event & select.EPOLLIN:  # there is data on socket available
                    print("EPOLLIN in PID: " + str(os.getpid()))
                    try:
                        clientsock, addr = sock.accept()
                        clientsock.close()
                        print("accepted and closed in PID: " + str(os.getpid()))
                    except Exception as e:
                        print("PID: " +  str(os.getpid()) + " " + str(e))

# we are in parent process, keep it live
while True:
    time.sleep(10)

The client  fires only one request to server:
---client.py---
import socket, time, select, sys

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('localhost',10000))
s.setblocking(False)
s.close()

after executing the "client.py" I am getting the following output from server:
EPOLLIN in PID: 9424
EPOLLIN in PID: 9425
PID: 9424 [Errno 11] Resource temporarily unavailable
accepted and closed in PID: 9425

as you can see, both of them get an EPOLLIN, BUT only one does the actual accept, the other 
one throws Exception.

A:

It works as designed: You want all children to get notified if they could accept a new client and they all get notified. At the moment epoll returns both can call accept. But if there is only a single client connecting, then accept can only return success once. If multiple clients are connecting then the other accept would succeed too.
So what you effectively want is to have only as much children woken up as clients are currently in the listen queue. Unfortunately there is no way to do something like this with the API defined by the system (it's not an issue of python). Thus, the usual way is just to ignore the EAGAIN and wait for the next client.

