Socket:send/4 timeout

For the socket:sendmsg(Socket, Msg, Timeout) or socket:send(Socket, Msg, Timeout) calls, is the call atomic in a sense that if there is a timeout, no part of the Msg will be written to the underlying socket buffer?

1 Like

I’m quite sure some others around here could comment in great detail, but that sounds right to me, in that you’re timing out on waiting for the select event (really Erlang -- erl_nif) to say “Hey, you are good to go on writing to the socket now!”. An oversimplification, but still and in other words, no write will be performed until a control signal is received.

Also see erl_check_io.c

Edit:

FWIW, I have read about cases where epoll can misfire FWIW, such that an FD isn’t really ready for writing or reading (iirc, this was around reads). I’d have to dig that back up and it’s not something I generally worry about myself, but I figured it’s so related to what you’re asking it’s worth mentioning.

For the TCP protocol the write to the socket buffer is atomic, but my question was more about whether the Msg passed to the send/3 function is written in chunks (especially if it represents an iolist), with the opportunity to timeout while finishing to write all chunks, or the operation is always atomic. I suppose it’s always atomic, but it doesn’t hurt to ask.

As to the epoll misfiring, it wouldn’t be an issue as the subsequent send(2) call would return an EAGAIN error anyway if there’s not enough space in the socket buffer, and I assume, the NIF implementation would loop again for the next epoll check.

Ahh yeah, well now that’s more interesting and would take digging into the code or getting an answer from an expert in this area of the code base. If the socket buffer is smaller than the size of your message, that can’t be atomic, right?

And yeah, I do believe the problematic misfire I’m thinking about is around reads (epoll says hey, there’s data for you, but not really :stuck_out_tongue: )

Yes, if the socket buffer can’t fit the data, you would get the EMSGSIZE error back from the kernel.

I checked the source code and the send/sendmsg calls are indeed atomic.

Though one might argue that it would make sense to loop there on return of EINT. Perhaps @raimo can comment?