Выбор нельзя безопасно использовать с программами, которые имеют более 1024 файловых дескрипторов в системе Linux. Это связано с тем, что базовый набор fd_set, используемый системным вызовом select, представляет собой буфер фиксированного размера, т. Е. Его размер выделяется во время компиляции, а не во время выполнения.
От человека 2 выберите:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
fd_set - это буфер фиксированного размера. Выполнение FD_CLR () или
FD_SET () со значением fd, которое отрицательно или равно или
больше чем FD_SETSIZE приведет к неопределенному поведению.
Более того, POSIX требует, чтобы fd был допустимым дескриптором файла.
Это означает, что если в вашей программе более 1024 файловых дескрипторов, и вы используете системный вызов select, вы получите повреждение памяти.
Если вы хотите использовать в своей программе более 1024 дескрипторов файлов, вы должны использовать опрос или epoll и убедиться, что вы никогда не используете select, иначе вы получите случайное повреждение памяти. Изменение размера таблицы дескрипторов файлов с помощью ulimit
очень опасно, если вы используете select
. Не делай этого.
Кажется, что Ruby действительно реализован с помощью системного вызова select, так что, хотя может показаться, что увеличение ulimit
работает, под капотом происходит повреждение:
https://github.com/ruby/ruby/blob/trunk/thread.c
Кроме того, некоторые несвязанные API в ruby, похоже, используют select (см. Thread_pthread.c), поэтому, вероятно, также небезопасно использовать их или любой код, который использует эти API в программе ruby, работающей с таблицей дескрипторов файлов больше 1024.