select() on sockets with timeout - c

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.

Related

Blocking sockets

I'm programing a small c linux local server. I've read a lot of documentation about threads, select function, nonblocking options, etc.
But I can't find any documentation about how to deal with client-side failures.
More specifically, working with threads and blocking sockets (not the best idea, I know, but I'm just running some tests), what happens when the client connection goes too slow? or what happens when the client doesn't close the connection properly (or not closing it at all)? Will my socket remain blocked? or the thread will never finish?
How to deal with this situations?
When using blocking sockets you have a couple of options.
One is to have one thread per client such that when you wait for information it doesn't matter how long you block. Note that when a connection is closed, the blocked operation will terminate. You can read a much more detailed description of this here.
An alternative to multiple threads is to use select. This allows you to wait on multiple file descriptors until some subset of the file descriptors are ready in the sense that they will not block. So basically instead of blocking on a single file descriptor during a read or write, you instead block on select and then you know you won't later block on the read/write.
Finally, you can use the asynchronous I/O functions, aio_read and aio_write which will perform the read/write asynchronously from the calling thread of execution.
Typically, sockets have some timeout value which can be controlled by the client. If a connection runs too slowly, or the connection dies for some reason (e.g. poor internet connectivity), the socket operation might continue to block until the timeout expires. With Linux sockets, when the timeout expires, you'll get an ETIMEDOUT errno that you can then handle later.
Typical values for the timeout are on the order of 60-300 seconds, but you can set them lower if you want to know about timeouts sooner. You can also set it to infinite, but this isn't recommended if you're using direct blocking calls since you could hang your thread forever.
On Linux (and any other system using the BSD socket API), you may change the socket timeouts using
struct timeval timeout;
timeout.tv_sec = 60;
timeout.tv_usec = 0;
setsockopt(socket, SOL_SOCK, SO_RCVTIMEO, &timeout, sizeof(struct timeval));

How can timeout be implemented given the blocking nature of recvfrom and sendto?

I am trying to achieve the TIMEOUT functionality in my UDP Stop-and-wait. That is, I make my receiver not send ACK on purpose and expect the sender re-transmit after the TIMEOUT.
However, as the the recvfrom documentation says:
If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking.
So both my sender and receiver get stuck at sendto() and recvfrom(). They both hang! THere most be a way so that I can make the code keep running so as to achieve the TIMEOUT.
How may I do that?
Take a look at the functions select poll and epoll. They can help with the timeout. They are also very useful when waiting on mulitple file descriptors (sockets)
Set the SO_RCVTIMEO option via the setsockopt() function. Then if the timeout triggers, recvfrom() will return -1 with errno set to either EAGAIN or EWOULDBLOCK.

what is the best way to handle new clients using select() in a server?

I want to write a asynchronous socket server in C, but before I do I'm doing some research. Looking at the select() socket example shown here: http://www.gnu.org/s/hello/manual/libc/Server-Example.html#Server-Example I can see that the example program will only accept one client per select loop (if I'm reading it right). So if there are 20 clients and two more try to connect, will it only accept the 21st client then process the other 20 (worst case, assuming all 20 others require reading) and THEN accept the 22nd? Would it be better if I break the loop after accepting a client so it can select() again and take care of all pending clients before processing connected ones? Or does that defeat the purpose of using select()? Thanks.
The server pattern shown in the example you linked to is fine; there isn't any significant problem introduced by the loop only accepting one socket per iteration.
The key point to keep in mind is that in a well-designed select() loop, the only place the process should ever block is inside the select() call. In particular, if coded correctly, the server will never block inside send(), recv(), or accept(). It's best to set all sockets to non-blocking mode (via fcntl(fd, F_SETFL, O_NONBLOCK)) in order to guarantee this behavior.
Given that, the precise ordering of "which clients get serviced first within any particular event loop iteration" doesn't matter, because all clients' sockets get handled very soon after they have data ready-for-read (or buffer space ready-for-write), and all new connections get accepted quickly.
select() leaves it up to the programmer to decide how to handle notifications. One call to select() can indicate that any or all sockets have bytes to be read and some connection requests to process. The application can process all the notifications before calling select() or process one notification before calling select() again.
You can use poll() on the listening socket after accept() to see if there are more clients waiting to connect.
Note the the number of concurrent connect-attempts is handled by the backlog parameter to listen(server_sock, backlog) - backlog is 1 in the sample you reference.

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