The select function is easy to use, and its working principle is also known to everyone. However, it may not be strictly observed in actual use, and it is indeed difficult to fully comply with it unless it is not used.
Select uses a bit table. Each FD corresponds to a bit in the table. The macro fd_setsize is the table size. The value of FD added to fd_set must be smaller than fd_setsize. Otherwise, the table will be out of bounds, suppose there is a piece of code as follows:
Fd_set readfds;
Fd_zero (& readfds );
Fd_set (FD, & readfds );
Therefore, the FD must meet the following requirements: FD <fd_setsize; otherwise, the problem may be crossed. This problem can be detected using memory detection tools such as valgrind and purify, but few people usually pay attention to it, it will be considered a negligible warning, and the consequence is a crash problem that cannot be understood.
You can use the ulimit command and the setrlimit function to modify the limit on the number of handles in the process. This does not affect the value of fd_setsize. Therefore, even if you use the ulimit command or the setrlimit function to change the allowed handle of the process to a large one, however, if the value of fd_setsize is not modified, crash may still occur.
Under what circumstances is this most likely to happen?
It is easy to occur in the server program, because the number of connections in the server program at the same time easily exceeds the default fd_setsize value, and the server code may be used by epoll, therefore, it does not have any problems, but there may be a client in the program. For example, if you use select to implement timeout connections, the problem arises. When the number of connections exceeds fd_setsize, the Select call at the timeout connection has crossed the border, and the process will crash in a location that may be completely irrelevant. The cost of locating this issue is high and there is no experience, it is difficult to locate it in a short time.
How can we avoid this problem? That is, do not use select as much as possible, instead use a safer poll function, because the arrays used by poll are maintained by the caller and can be completely avoided.