Server reaction after select() returns an error

Started by
5 comments, last by md_lasalle 16 years, 11 months ago
imagine you're running a server, with let's say 20 clients, you have 1 fd_set where you keep all your fd's. Then a client joins, you add it to the fd_set and then 2 seconds after he joined, select returns an error, maybe because his socket got corrupted?! How should the server application react ? Because we can't assume it's the last created fd that is not a valid socket anymore. My first idea was to have an fd_set PER CLIENT, which means i would select() for each client on each update frame, what do you think of this approach ? Would this be considered a bad approach because of fd_set's size being useless since we're gonna store only one fd in it ? Or more generally, what is the best way to react when select() returns an error ? should i run throught each fileDescriptors i currently have and test ( if possible ) if they are still valid ? Thanks [Edited by - md_lasalle on April 21, 2007 5:06:51 PM]
Advertisement
What do you mean by a "corrupt" socket?

If some player disconnects, select() will return the socket as readable, and read() will return zero. Also, you can look into the exception bits for error conditions (see the select() manual page). It's perfectly possible to tell who should be removed from the fd_set using the existing API.
enum Bool { True, False, FileNotFound };
Taken from this article : http://www.uwm.edu/cgi-bin/IMT/wwwman?topic=select(2)&msection=2


When select() returns an error, including a process interrupt, the I/O
descriptor sets pointed to by the readfds, writefds, and exceptfds parame-
ters remain unmodified.




So if i can't check the exception fd... what else can I do ?

I still could check errno, but how would it helps determine which socket fd is bad. Is errno available on Windows OS ?


Thanks



ERRORS

The select() function sets errno to the specified values for the following
conditions:

[EBADF] One or more of the I/O descriptor sets specified an invalid file
descriptor.

[EINTR] A signal was delivered before the time limit specified by the
timeout parameter expired and before any of the selected events
occurred.

[EINVAL] The time limit specified by the timeout parameter is invalid.

The nfds parameter is less than 0, or greater than or equal to
FD_SETSIZE.

One of the specified file descriptors refers to a STREAM or mul-
tiplexer that is linked (directly or indirectly) downstream from
a multiplexer.

[EAGAIN] [Digital] Allocation of internal data structures failed. A
later call to the select() function may complete successfully.

Quote:When select() returns an error


Note that this is when the select() funciton itself is called in error, not when some socket passed to it has an error condition.

A socket/file descriptor will not be "invalid" until you call close()/closesocket() on it. It may, however, perhaps be disconnected (so that you can't send data), or full-buffered (so that sending data would block). Big difference.
enum Bool { True, False, FileNotFound };
Ok so, if select returns an error, i should disconnect everyone from the server, to make sure i kill the faulty socket ? What would you suggest ?
There is no such thing as a "faulty socket." If select returns an error, saying that you specified a bad socket, meaning a socket identifier that's not actually a socket, then there is a bug in your program, and you should fix the bug. If select returns EINTR, specifying that it was interrupted by a signal, you should do whatever you do for other signal handling cases (which might be to just re-try the call). If select returns EAGAIN, your best bet might be to realize that the system is over-loaded, log a message to that effect, and quit the process. That shouldn't happen during normal operating conditions in any kind of reasonably provisioned system.
enum Bool { True, False, FileNotFound };
Thank you, i'll check what kind of error select returns and make my app behave accordingly

This topic is closed to new replies.

Advertisement