1

There's something I miss when it comes to epoll

In Win32, If a socket is registered under some IOCP and no data is available for the socket to read, then issuing an asynchronous read action using ReadFile with some overlapped struct will return false and the error code is WSA_IO_PENDING.

When data is available, then the IOCP pulls out the relevant overlapped, the buffer given to ReadFile contains the newly-read-data and you can continue from there.

When it comes to linux and epoll, I don't get it. If you register a socket under some epoll object and no data is available, read will just return -1 and errno is EWOULDBLOCK or EAGAIN. I also understand that monitoring EPOLLIN is semi-helpfull, as EPOLLIN talks about being able to read from the socket, not about actual existing data to read.

how can one tell the socket "hey, I want X bytes of data or less to be written this buffer, If you don't have the data now, it's fine - give it to me when you do. notify me when the data is stored in the buffer"?

Is it possible with an epoll object as it is possible with IOCP?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
David Haim
  • 25,446
  • 3
  • 44
  • 78
  • 1
    "*notify me*" - How? – melpomene Feb 21 '19 at 15:22
  • @melpomene in any way. for example, by unblocking the thread stuck on `epoll_wait`, signaling, etc. – David Haim Feb 21 '19 at 15:23
  • 3
    Wait, you have a thread? Why bother with epoll then? Just do a blocking read. – melpomene Feb 21 '19 at 15:24
  • @melpomene c'mon, be serious. – David Haim Feb 21 '19 at 15:24
  • 1
    I am serious. WTF? – melpomene Feb 21 '19 at 15:24
  • 3
    _`EPOLLIN` talks about being able to read from the socket, not about actual existing data to read_ - `EPOLLIN` means there is data or error in the socket. – Maxim Egorushkin Feb 21 '19 at 15:25
  • 3
    I think you have the workflow on non Windows OSes backwards. Use `epoll` (or `poll()` or `select()` or on BSDs `kqueue`) to see when the socket can be successfully read from without blocking, and then `read()` it. If the polling function doesn't indicate that the socket is readable, don't bother trying to. – Shawn Feb 21 '19 at 15:27
  • There is a posix asynchronous io api for being notified when an operation completes, but it's poorly supported and a pain to use. The glibc implementation doesn't even use the relevant Linux syscalls; it uses threads to emulate asynch stuff. – Shawn Feb 21 '19 at 15:31
  • @Shawn aha.. I get it now. wow, I actually prefer the windows approach. If you post you comments as an answer, I'll accept it. – David Haim Feb 21 '19 at 15:32
  • 2
    @melpomene asynchronous-io != io on another thread. read about the 10k problem. – David Haim Feb 21 '19 at 15:32
  • 1
    @DavidHaim It was you who brought up the "unblock a thread stuck in a function call" thing. That's exactly what a blocking read is. – melpomene Feb 21 '19 at 15:36
  • @melpomene *sigh*. ok. – David Haim Feb 21 '19 at 15:38
  • 1
    I think it is not possible to do that. IOCP implements proactor model, while epoll() -- reactor model. There is a glibc threaded wrapper that imitates proactor (`man aio`), but since it is thread-based, you most likely don't want to use it. There is also "linux aio" (`man io_submit`), but it is supported only for files (not for sockets) and only for some filesystems. – gudok Feb 21 '19 at 15:53
  • Have a look at how [asio](https://github.com/chriskohlhoff/asio/blob/master/asio/include/asio/detail/impl/epoll_reactor.ipp#L470) does it with `epoll_wait`. – rustyx Feb 21 '19 at 20:55
  • There’s this article which is a good survey of Linux existing asynchronous IO solutions and echoing your question. Great read: http://davmac.org/davpage/linux/async-io.html – KFL Jan 29 '21 at 20:04

2 Answers2

2

There is no API that would notify you when X data is available, or buffer reads for you. There are APIs that will unblock when any non-zero amount of data is available. One of these APIs is epoll_wait. You will need to read and collect X data yourself in your buffer.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
0

There is no Linux sockets API which would do what you want - i.e. perform the operation when the socket is available. You will always have to perform the read explicitly in the code.

The best you can do is to have a non-blocking IO with poll multiplexing, or a blocking IO with a thread per socket.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • as much as I appreciate the answer, I have to disagree and disclaim. IOCP doesn't work by launching the action on another thread. otherwise IOCP is just a lame threadpool. plus, if you don't remember what is the API then there's nothing I can get from your answer. anyway thanks, any help is appreciated. – David Haim Feb 21 '19 at 15:36
  • @DavidHaim there was a typo in my answer - it should have read 'There is **no** Linux socket API...' Sorry for that. As for IOCP mechanism, looks like I was mistaken about it - I will just remove it, it servers no purpose anyways. – SergeyA Feb 21 '19 at 15:56