Every answer says epoll is thread-safe but that's not true.
epoll calls are thread safe at the most basic level: when considering the list of file descriptors, the events, etc. And especially using EPOLLET
will allow only only one thread to receive an event whereas level-triggered epoll will potentially deliver the same event to multiple threads, which causes the thundering herd other mentioned elsewhere in this page.
However it's not thread safe at the scheduling level: when a thread receives an event (say with EPOLLET
it's woken up for the first packet that comes from the network), then while it's processing other file descriptors in the long list of events, the next packet on the network arrived and triggers another event that another thread picks-up. Now you've got two threads concurrently running to retrieve data from the network.
One can imagine several scenarios where this could break an app, which depend on the read patterns. In addition to this race, OS scheduling can mess with the timings and favor one of the two threads which is problematic when a thread needs multiple reads (e.g. it first reads the size then the payload but got time-sliced in-between).
Even if the first thread reads everything, the second thread will read nothing (unless data has arrived from the network between the two reads). Say this "everything" contains half an http request. While it parses that half request, the 2nd half arrived on the network and another thread got an event and reads the second half. How do you handle that without synchronization?
The approach you describe of using the same socket in multiple threads is only thread safe if you can ensure two things:
- Reads will atomically retrieve a number of complete messages which is near impossible to ensure, due to how networking works (path mtu, TCP window...). In practice that only works with fixed length messages.
- Messages can be processed out of order.
epoll
is thread-safe. Yes, you can do it. Just search around for details, SO and Google are full of this information. – Chiarra