Non Blocking recv() in C Sockets - c

I am using an infinite loop in sockets in which if it receives some data it should receive it or if it wants to send data it sends. Something like given below. I am using select. I have only one socket sd.
fd_set readsd;
int maxsd = readsd +1;
// all those actions of setting maxsd to the maximum fd +1 and FDSETing the FDs.
while(1)
{
FD_ZERO(&read_sd);
FD_SET(sd, &read_sd);
if(FD_ISSET(sd, &readsd))
{
//recv call
}
else
{
//send call
}
}
As far as I know, select selects one of the socket descriptors on which data arrives first. But here I have only one socket, and I want to recv if there is some data or I want to send otherwise.
In that case, is the code given above fine? Or there is some other option for me which I don't know about?

In that case, is the code given above fine ?
I don't see any call to select. Also, if “maxsd” is designed to be the first argument of select, its value is wrong : it must be the bigest file descriptor +1. Anyway, you could simply call recv with the flag MSG_DONTWAIT, in which case it will return an error if there is no data to read.

It kind of depends... First of all, you actually do have a select call in your real code?
Now about the blocking... If select returns with your socket set in the read-set, then you are guaranteed that you can call recv without blocking. But there are no guarantees about the amount of data available. If you use UDP then there will be at least one (hopefully complete) packet, but if you use TCP you may get only one byte. For some protocols with message boundaries, you might not get full messages, and you have to call recv in a loop to get all of the message, and unfortunately this will sooner or later cause the recv call to block.
So in short, using select helps, but it does not help in all cases. The only way to actually guarantee that a recv call won't block is to make the socket non-blocking.

Im not very sure about what you are trying to do, so I can think about two options:
Set a socket to be non-blocking
Since seems like you have only one socket, you can set the socket to non-blocking mode using fcntl and call the recv()
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL) | O_NONBLOCK);
// if fcntl returns no error, sock is now non-blocking
Set the select timer
Using select you can set a timer to force the return after some time happened even if no data was received.

First, I cannot find any select in your code.
However, you may call fcntl(fd, F_SETFL, flags | O_NONBLOCK) first to make your socket non-blocking. Then check if errno == EWOULDBLOCK when you cannot read anything from recv. You need not to use select in this case.

Related

Is it possible to do epoll on accept event?

Let's suppose I've created a listening socket:
sock = socket(...);
bind(sock,...);
listen(sock, ...);
Is it possible to do epoll_wait on sock to wait for incoming connection? And how do I get client's socket fd after that?
The thing is on the platform I'm writing for sockets cannot be non-blocking, but there is working epoll implementation with timeouts, and I need to accept connection and work with it in a single thread so that it doesn't hang if something goes wrong and connection doesn't come.
Without knowing what this non-standard platform is it's impossible to know exactly what semantics they gave their epoll call. But on the standard epoll on Linux, a listening socket will be reported as "readable" when an incoming connection arrives, and then you can accept the connection by calling accept. If you leave the socket in blocking mode, and always check for readability using epoll's level-triggered mode before each call to accept, then this should work – the only risk is that if you somehow end up calling accept when no connection has arrived, then you'll get stuck. For example, this could happen if there are two processes sharing a listening socket, and they both try to accept the same connection. Or maybe it could happen if an incoming connection arrives, and then is closed again before you call accept. (Pretty sure in this case Linux still lets the accept succeed, but this kind of edge case is exactly where I'd be suspicious of a weird platform doing something weird.) You'd want to check these things.
Non-blocking mode is much more reliable because in the worst case, accept just reports that there's nothing to accept. But if that's not available, then you might be able to get away with something like this...
Since this answer is the first up in the results in duckduckgo. I will just chime in to say that under GNU/Linux 4.18.0-18-generic (Ubuntu 18.10).
The asynchronously accept an incoming connection using one has to watch for errno value EWOULDBLOCK (11) and then add the socket to epoll read set.
Here is a small shot of scheme code that achieves that:
(define (accept fd)
(let ((out (socket:%accept fd 0 0)))
(if (= out -1)
(let ((code (socket:errno)))
(if (= code EWOULDBLOCK)
(begin
(abort-to-prompt fd 'read)
(accept fd))
(error 'accept (socket:strerror code))))
out)))
In the above (abort-to-prompt fd 'read) will pause the coroutine and add fd to epoll read set, done as follow:
(epoll-ctl epoll EPOLL-CTL-ADD fd (make-epoll-event-in fd)))
When the coroutine is unpaused, the code proceed after the abort to call itself recursively (in tail-call position)
In the code I am working in Scheme, it is a bit more involving since I rely on call/cc to avoid callbacks. The full code is at source hut.
That is all.

When using select(), can i add same descriptor in both readfds and writefds set?

My program is going to use a single socket to read and write. Messages from multiple clients will be written to the same socket and the responses received will be multiplexed back to the respective clients.
When making select() call, can I set the same single fd in readfds and writefds sets in order to detect whether the socket is ready for read or write? I plan to read or write on the socket based upon the the status that select() would return.
Yes, you can and that's a very typical thing to do.

select() on sockets with timeout

Inside the read FD_SET I have several sockets:
the main socket listening for new connections
accepted sockets listening for incoming data.
I set the timeout for 30 seconds and called select(). I quickly noticed the behavior is different for each:
When a new client connects on the listening port, it returns immediately from blocking.
When an already connected client sends a message, it blocks for the entire 30 seconds.
Is there a way I can make it return immediately in the second case?
My guess is either you aren't including all your sockets in the correct fd_set or you aren't passing in the highest numbered file descriptor plus 1 as the first parameter (nfds below) to the select call.
select(nfds, &readfds, &writefds, &execptfds, &timeout);
One of the most common errors with select(2) is not re-initializing fd_sets before calling select() again.
I constantly use such select()s without any problem.
Probably you do something wrong with accepted sockets waiting on data. Could you please post code fragment? Especially most important is how you set first select() parameter.

select on UDP socket doesn't end when socket is closed - what am I doing wrong?

I'm working on Linux system (Ubuntu 7.04 server with a 2.6.20 kernel).
I've got a program that has a thread (thread1) waiting on a select for a UDP socket to become readable.
I'm using the select (with my socket as the single readfd and the single exceptfd) instead of just calling recvfrom because I want a timeout.
From another thread, I shutdown and close the socket.
If I do this while thread1 is blocked in a recvfrom, then the recvfrom will terminate immediately.
If I do this while thread1 is blocked in a select with a timeout, then the select will NOT terminate immediately, but will eventually timeout properly.
Can anyone tell me why it is that the select doesn't exit as soon as the socket is closed? Isn't that an exception? I can see where it isn't readable (obviously), but it's closed, which seems to be to be exeptional.
Here's the opening of the socket (all error handling removed to keep things simple):
m_sockfd = socket(PF_INET, SOCK_DGRAM, 0);
struct sockaddr_in si_me;
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(port);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(m_sockfd, (struct sockaddr *)(&si_me), sizeof(si_me)) < 0)
{
// deal with error
}
Here's the select statement that thread1 executes:
struct timeval to;
to.tv_sec = timeout_ms/1000;// just the seconds portion
to.tv_usec = (timeout_ms%1000)*1000;// just the milliseconds
// converted to microseconds
// watch our one fd for readability or
// exceptions.
fd_set readfds, exceptfds;
FD_ZERO(&readfds);
FD_SET(m_sockfd, &readfds);
FD_ZERO(&exceptfds);
FD_SET(m_sockfd, &exceptfds);
int nsel = select(m_sockfd+1, &readfds, NULL, &exceptfds, &to);
UPDATE: Obviously (as stated below), closing the socket isn't an exceptional condition (from select's point of view). I think what I need to know is: Why? And, Is that intentional?.
I REALLY want to understand the thinking behind this select behavior because it seems counter to my expectations. Thus, I obviously need to adjust my thinking on how the TCP stack works. Please explain it to me.
Maybe you should use something else to wake up the select. Maybe a pipe or something like that.
UDP is a connectionless protocol. Since there is no connection, none can be broken, so the consumer doesn't know that the producer will never send again.
You could make the producer send an "end of stream" message, and have the consumer terminate upon receiving it.
I think the most obvious solution is that being closed isn't considered an exceptional condition. I think the root of the problem is, that you're not really embracing the philosophy of select. Why on earth are you fiddling around with the socket in another thread, that sounds like a recipe for disaster.
Could you not send a signal (e.g. USR2) to the thread which would cause select() to return with EINTR?
Then in the signal handler set a flag telling it not to restart the select()?
That would remove the need for waiting on multiple file descriptors, and seems a lot cleaner than using a pipe to kill it.
I would say the difference is that recvfrom is actively trying to read a message from a single socket, where select is waiting for a message to arrive, possibly on multiple handles, and not necessarily socket handles.
Your code is fundamentally broken. Variations on this mistake are common and have caused serious bugs with massive security implications in the past. Here's what you're missing:
When you go to close the socket, there is simply no possible way you can know whether the other thread is blocked in select or about to block in select. For example, consider the following:
The thread goes to call select, but doesn't get scheduled.
You close the socket.
In a thread your code is unaware of (maybe it's part of the platform's internal memory management or logging internals) a library opens a socket and gets the same identifier as the socket you closed.
The thread now goes into select, but it's selecting on the socket opened by the library.
Disaster strikes.
You must not attempt to release a resource while another thread is, or might be, using it.

How to stop a read operation on a socket?

From one thread I got the following code:
int next_stuff(char **code){
...
len=read(file_desc,buffer+end_len,packet_size-end_len);
if(len<=0)
{
if(len==-1 && errno==EAGAIN) return(0);
else return(-1);
}
...
}
while (next_stuff(&buff) == 0)
{
...
}
On the other thread I'd like to finish that socket and exit this operation, but only doing a
close(file_desc);
does not cause read to return nonblocked. Am I missing something?
EDIT:
shutdown does not work as well. And I am trying that on Linux 2.6.23
shutdown(fd, SHUT_RD);
$ man -s 2 shutdown
NAME
shutdown -- shut down part of a full-duplex connection
SYNOPSIS
#include <sys/socket.h>
int shutdown(int socket, int how);
DESCRIPTION
The shutdown() call causes all or part of a full-duplex connection on the socket
associated with socket to be shut down.
If how is SHUT_RD, further receives will be disallowed. If how is
SHUT_WR, further sends will be
disallowed. If how is SHUT_RDWR, further sends and receives will be disallowed.
RETURN VALUES
The shutdown() function returns the value 0 if successful; otherwise the value -1 is
returned and the global variable errno is set to indicate the error.
In general, if you do not want blocking socket calls, you would use select() to see if the socket is ready to read, write, or is in the error state. In addition, pass a timeout value to select() so that this call isn't blocking forever. After the select() call returns, you can see if the application wants to quit and if so do the "right" thing (that's for you to decide).
If your read() call is nonblocking, it should return fairly fast, as all it will be doing is inserting memory.
To prevent doing any damage, you would use a mutex around your call to read() and close() such that they cant both run at the same time.
If your socket is blocking, i think you should make it nonblocking.
The other answers about non-blocking sockets are good, and I recommend recoding to use that approach.
As a direct answer to your question, though, try calling shutdown() and see if that will break the other thread out of read. I'm afraid close() is just decrementing the usage count, while shutdown() will actively tear down the socket.
I don't think you've provided enough information to answer this question, yet. For example if the socket that you've opened is UDP, then a close on the sending side will have no effect on the receiving side. If it is TCP, then something else is broken. I suggest that if you are really dealing with sockets, you use recv or recvfrom instead of read.
In the case of TCP, your read will return 0 bytes, an indication that the other side has closed the connection.
If you are really doing this between two threads instead of two processes, a pipe may be more appropriate. That's not to say that a pipe could not also be used between two separate processes, it just takes a bit more set up in that case.

Resources