Socket recv (blocking) fails with errno EAGAIN - resource temporarily unavailable - sockets

I am implementing a UNIX domain socket Inter Process communication code and I hit this error randomly - "errno 11: Resource temporarily unavailable" while trying to read from the socket. I use MSG_PEEK to read the number of bytes from the socket, and allocate bytes for receive buffer, and read the actual data.
The socket is a blocking socket and I do not have any code to have non-blocking (in all, accept/read/write). Any pointers on what could cause this on a blocking socket read? From the man page of MSG_PEEK, it seems like EAGAIN could be returned when socket is marked as non-blocking, using O_NONBLOCK.
The failure happens on the recv call below.
char temp_buffer[BUFFER_MAX];
num_bytes = recv(_connection_fd, &temp_buffer, BUFFER_SIZE_MAX, MSG_PEEK | MSG_TRUNC);
if (num_bytes < 0) {
LogError("Error reading from socket. %s", strerror(errno));
close(_connection_fd);
return -1;
}
.....
<Allocate memory>
.....
// Read actual data
num_bytes = read(_connection_fd, buffer, num_bytes);
...
<Send response back to client>
<Close socket descriptor>

It may also happen to blocking socket and blocking recv, if socket has timeout SO_RCVTIMEO option set (default is 0). BTW, did you consider select() before recv()?

Related

(LwIP) socket send() returns "Connection already in progress"

I'm maintaining an embedded system that uses LwIP. The relevant code is as follows (edited):
iobSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
connectRC = connect(socket, &serverAddress, sizeof(struct sockaddr));
FD_SET(socket, &fdset);
selectRC = select((socket) + 1, NULL, &fdset, NULL, &tv);
sendRC = send(iobSocket, dout, strlen(dout), 0);
This seems to work. When I remove the select() call, however, I get an error on the send() which sets errno to 119 or Connection already in progress. This error code isn't documented in the send() man pages.
Can someone tell me why the select() command is even necessary here, and why I might be getting an undocumented error without it?
Thank you.
Error code 119 is EINPROGRESS. It means the socket is operating in non-blocking mode 1, and the previous connect() operation hasn't finished yet, which is why the send() fails.
1: Which means, there must be more code that you are not showing, as sockets are normally in blocking mode when they are initially created, and require explicit code to put them into non-blocking mode, such as via fcntl(F_SETFL, O_NONBLOCK);.
Using select() to test the socket for writability allows your code to wait until the socket is actually done connecting and is ready for sending.
This is explained in the man page for connect():
RETURN VALUE
If the connection or binding succeeds, zero is returned. On error, -1 is returned, and errno is set to indicate the error.
ERRORS
The following are general socket errors only. There may be other domain-specific error codes.
...
EINPROGRESS
The socket is nonblocking and the connection cannot be completed immediately. (UNIX domain sockets failed with EAGAIN instead.) It is possible to select(2) or poll(2) for completion by selecting the socket for writing. After select(2) indicates writability, use getsockopt(2) to read the SO_ERROR option at level SOL_SOCKET to determine whether connect() completed successfully (SO_ERROR is zero) or unsuccessfully (SO_ERROR is one of the usual error codes listed here, explaining the reason for the failure).

Handle mutiple UDP client

I have a single server and multiple UDP clients in my setup and each sending a boolean string (true/false 5 byte max) at regular intervals of time (few milliseconds). Based on which i am determining if the device is alive or not.The number of clients are unknown before starting the program and using c++ as my programming language.
Is it possible to have a multi threading in UDP socket connection ? I came across and example for TCP where they create a new socket descriptor and spawn a thread. If its possible to write a multi threading for UDP serves please provide example/reference code.
During
while (true)
{
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,
(struct sockaddr *)&cient_addr, &client_addr_len)) == -1)
{
perror("recvfrom");
exit(1);
}
// Process buffer...
// Do something with buffer
}
In multiple client scenario if i receive message from one client its copied to local buffer of maximum buffer size. And while process this message if we receive one more message from another client where will this message store intermittently before reading to local buffer ? Does the socket file descriptor has its own buffer ?
What happens if both clients send message at the same time ? Only one is read to local buffer what will happen to another message ? will it wait for the next recvfrom ?
I read that if Maximum buffer is less that the message / packet size received then the recvfrom will only read the max buffer length and might through some error...Although all of my client only send 5 bytes maximum..If I assign Maximum bytes to 1024 bytes which is way far than expected what prices am I gonna pay ?
Thank you.

(recv() == 0) means disconnected or timed out? (sockets, Linux&Windows)

I have set a timeout on my blocking socket ..
DWORD to = 1200;
if (setsockopt (soc, SOL_SOCKET, SO_RCVTIMEO, (char *)&to, sizeof(to))) {
...
}
In the case that recv () then returns zero, how can I tell this is link disconnected or read timed out? If it's t/o I would like to read more, if it's discon I would like to take other action. I realise I could just remove the t/o, then I would know it's discon, but I also need to routinely monitor how the read process is progressing.
Any help much appreciated. Cheers - Rich
From the SO_RCVTIMEO section of the man page for socket:
...if no data has been transferred and the time‐out has been reached,
then -1 is returned with errno set to EAGAIN or EWOULDBLOCK, or
EINPROGRESS (for connect(2)) just as if the socket was specified to
be non‐blocking.
From the man page for recv:
These calls return the number of bytes received, or -1 if an error
occurred. In the event of an error, errno is set to indicate the
error.
When a stream socket peer has performed an orderly shutdown, the
return value will be 0 (the traditional "end-of-file" return).
Datagram sockets in various domains (e.g., the UNIX and Internet
domains) permit zero-length datagrams. When such a datagram is
received, the return value is 0.
The value 0 may also be returned if the requested number of bytes to
receive from a stream socket was 0.
A call to recv will return 0 on disconnect, or if a zero-length datagram is received, or if the requested number of bytes is 0.
A call to recv will return -1 on any error, including a timeout. You need to examine errno to differentiate between a timeout versus some other error.

will poll() return immediately for UDP socket if there are data not read from last read()?

An existing program is written this way for UDP socket (in blocking mode):
while (true) {
poll();
if (POLLIN is set) {
read(fd, buf, bufSize);
}
}
For UDP, each read() read 1 and only 1 datagram (packet). If there are multiple packets available in the socket recv buf, the above code reads 1 packet only at each read(). My question is: will the next poll() return immediately, thus the above code still can read from socket very quickly? Or could next poll() wait until there is new packet arrives on the socket thus the code effectively falls behind in reading?
The doc seem to suggest that next poll() will return immediately as long as there are data in the buffer. But the code seem to fall behind in reading, and I don't know the cause is in the above code or somewhere else.
The preferred way is likely:
set the socket to non blocking
read in the loop until errno = EWOULDBLOCK or EAGAIN
Thanks.
If there is already data in the socket buffer when poll() is called, it should signal POLLIN immediately if POLLIN is requested, yes. It should not wait for the next packet to arrive in the buffer before signaling POLLIN.

BlockingIOError when send to non-blocking UNIX soket with SO_SNDBUF

I use nonblocking UNIX UDP socket to transfer data from one process to another:
audio_s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
audio_s.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 5500000)
audio_s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 5500000)
audio_s.setblocking(0)
try:
os.remove(SOCKET_PATH)
except FileNotFoundError as e:
pass
audio_s.bind(SOCKET_PATH)
And I often send data to remote process:
audio_s.sendto(data, REMOTE_SOCKET_PATH)
But sometimes (very rare) I catch BlockingIOError: [Errno 11] Resource temporarily unavailable on sendto call. What reason can be for this? Resource temporarily unavailable looks like very generic sentence.
Is it possible to know more detailed information? For example send buffer overflowed of remote receive buffer overflow? Are these possible reasones? or only 1 of them?
Can I control current datagram count in send/receive buffer?
What is correct way to process or avoid this situation?
If I remove line with:
audio_s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 5500000)
it works without this exception
Errno 11 is EAGAIN, from 'man sendto':
[EAGAIN] The socket is marked non-blocking and the requested operation would block.
Good explanations are there:
When a non-blocking send() only transfers partial data, can we assume it would return EWOULDBLOCK the next call?
and there:
EAGAIN Error: Using Berkeley Socket API