I want to increase FD_SETSIZE macro value for my system. Is there any way to increase FD_SETSIZE so select will not fail
-
yes, In my case I need it about 2048 . Is there any way to set it ? – Vivek Goel Nov 02 '11 at 06:07
-
because I want to increase my server limit to support that much of connection. – Vivek Goel Nov 02 '11 at 06:55
-
6No offense, but thinking about increasing `FD_SETSIZE` is a pretty dumb thing to do. 2048 concurrent connections (or rather, more than that) is well within the range where `epoll_wait` greatly outperforms both `select` and `poll` simply because it _doesn't need to_ copy 8 kilobytes of data every time and doesn't need to iterate over two thousand descriptors every time. – Damon Aug 30 '13 at 13:22
-
Real answer is : NO not under linux. For BSD and Windows it is possible to redefine FD_SETSIZE. Trying to do it require hacking and it will lead for sure to future problem. So prefer usage of poll whenever maximum descriptor value can be over 1024. – philippe lhardy Dec 15 '13 at 21:08
-
Real answer is: YES under Linux. For Furcadia, an MMO which runs on Linux, we modified the FD_SETSIZE constant so that we could have all players (tens of thousands) on the same server. It's worked fine since 1996, across all the intervening versions of Linux and server upgrades and migrations. – Dewi Morgan Aug 01 '23 at 17:19
5 Answers
Per the standards, there is no way to increase FD_SETSIZE
. Some programs and libraries (libevent comes to mind) try to work around this by allocating additional space for the fd_set
object and passing values larger than FD_SETSIZE
to the FD_*
macros, but this is a very bad idea since robust implementations may perform bounds-checking on the argument and abort if it's out of range.
I have an alternate solution that should always work (even though it's not required to by the standards). Instead of a single fd_set
object, allocate an array of them large enough to hold the max fd you'll need, then use FD_SET(fd%FD_SETSIZE, &fds_array[fd/FD_SETSIZE])
etc. to access the set.

- 208,859
- 35
- 376
- 711
-
I am using an third party library. Is there any easy way to patch the code with your suggestion or replacing with pool ? – Vivek Goel Nov 02 '11 at 06:40
-
6@dns: That is false documentation. :-) Please read http://pubs.opengroup.org/onlinepubs/9699919799/functions/pselect.html. OK, joking aside, please explain what you think is "false" about my answer. – R.. GitHub STOP HELPING ICE May 14 '13 at 14:15
-
4as per microsoft themselves "Per the standards, there is no way to increase FD_SETSIZE" is false because and I'm quoting word for word from Microsoft themselves: "This value is used in constructing the fd_set structures used in select(). The default value in WINSOCK.H is 64. If an application is designed to be capable of working with more than 64 sockets, define the manifest FD_SETSIZE in every source file before including WINSOCK.H." please read http://support.microsoft.com/kb/111855 – BrierMay Aug 11 '13 at 23:30
-
3ok well then to fit in with the "standards" you can also increase it on Linux/unix/mac varients by simply changing #define __FD_SETSIZE 1024 the following 2 files /usr/include/bits/typesizes.h /usr/include/linux/posix_types.h nonethe less you stated that you cannot increase it and you can so either way the answer is false – BrierMay Aug 13 '13 at 17:37
-
9That's also not standard. That's an implementation-specific hack. I agree that on many implementations you can make an implementations-specific hack of this form, but it's not correct per the standards. – R.. GitHub STOP HELPING ICE Aug 13 '13 at 17:41
-
2if i recall op didn;t ask about standards they asked how to change it so your answer is misleading in telling people you can not change when you can that is why the original comment saying the answer is false. you CAN change it you said you cannot change it – BrierMay Aug 13 '13 at 17:44
-
Wrong. You have always been able to #define FD_SETSIZE prior to #include
– Andrew Hacking Sep 09 '14 at 07:34 -
7@AndrewHacking: When will people get tired of posting wrong comments on this? Yes, some implementations allow it. No, it is not not valid per the specification of the interface. The relevant text is... – R.. GitHub STOP HELPING ICE Sep 09 '14 at 15:03
-
2...[XSH 2.2.2 The Name Space](http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_02_02) "Applications shall not declare or define identifiers with the same name as an identifier reserved in the same context. Since macro names are replaced whenever found, independent of scope and name space, macro names matching any of the reserved identifier names shall not be defined by an application if any associated header is included." – R.. GitHub STOP HELPING ICE Sep 09 '14 at 15:06
-
1@R.. I never said I cared about being a POSIX zealot and specifically said *you are able to*. In all the production POSIX like systems I have used over the last 26 years this has worked and was indeed mandatory for servers that need to service more than a few connections. I'm not sure what relevant POSIX like system you are referring to where this doesn't work. You propose a convoluted broken approach which cannot wait on the full set of file descriptors in order to "get around" some wording in a spec when all implementations provide non-posix extensions. – Andrew Hacking Sep 10 '14 at 06:13
-
@AndrewHacking: No. In my approach you can wait on all file descriptors with a single `select` call. Perhaps you misread it. – R.. GitHub STOP HELPING ICE Sep 10 '14 at 15:27
-
1@R.. So you agree with me that the OS syscall WILL accept file descriptor sets greater than the default FD_SETSIZE and DO NOT bounds check to the FD_SETSIZE defined in
as you erroneously claim. You can't have it both ways. – Andrew Hacking Sep 11 '14 at 01:16 -
2@AndrewHacking: The system call on most (all?) systems I'm aware of will accept arbitrary-size sets, probably because either (a) it's made to work with a mix of different userspace implementations that have different values for `FD_SETSIZE`, or (b) it's made to work with a userspace implementation that provides a method to request a non-default `FD_SETSIZE` (either via defining it before including the header, or by some other mechanism). On the other hand, there is no guarantee that defining `FD_SETSIZE` before including `sys/select.h` will work; on at least some systems, it's an error. – R.. GitHub STOP HELPING ICE Sep 11 '14 at 04:48
-
select()/poll() copy the descriptor sets between userspace and kernelspace, hence why they don't scale well. The FD_SETSIZE constant has no bearing on the kernel limit as its defined by the kernel, not a header file and the kernel will never let you open more files than its internal limit. Your point about POSIX correctness is not saved by your approach as select()/poll() are defined in terms of FD_SET, your approach is no more correct yet it is more complex. Your claims about "robust implementations may check" are theoretical and not true in practice. State the systems where this is true. – Andrew Hacking Sep 11 '14 at 13:55
-
3@AndrewHacking: At this point you're grasping for straws trying to "prove my answer is wrong" or something, and I'm not quite sure why. the scale at which `poll` becomes non-competitive is something like 50k-100k file descriptors, and when you have that many, other factors are likely to be your bottleneck. In particular, bahamut-ircd on dalnet performed fine with `poll` in the 1990s with 70k clients on the highest-load servers. So the argument that copying the set from userspace "doesn't scale well" does not hold water. – R.. GitHub STOP HELPING ICE Sep 11 '14 at 14:00
-
3@AndrewHacking: As for my claim about "robust implementations may check", read `bits/select2.h` provided by glibc. It's used whenever `_FORTIFY_SOURCE` is active, and it actively checks the fd number against an *internal constant* (not the public `FD_SETSIZE` which you wrongly claim you can modify) and aborts the program (valid, since UB was invoked) if the fd number is out-of-range. – R.. GitHub STOP HELPING ICE Sep 11 '14 at 14:03
-
So what you are saying is that when you go out of your way to use a NON POSIX, and non standard setting on an inherently non posix compliant system it complains with a warning. Perhaps you should qualify your statement in your answer for this very narrow failure case. – Andrew Hacking Sep 11 '14 at 14:39
-
1@AndrewHacking: No. `_FORTIFY_SOURCE` is perfectly POSIX conforming and it's the default on most Linux distributions nowadays. As in **your apps will break if you do this broken hack**, and when distros go to package your app, their choices will be to fix your bugs (likely not worth their time), disable `_FORTIFY_SOURCE` for the one package (which, since it's buggy software that's known to be invoking UB, is probably going to expose security holes which would otherwise have been partially-plugged by the default hardening), or just omit your software from packaging as sub-standard quality. – R.. GitHub STOP HELPING ICE Sep 11 '14 at 14:44
-
Its not a POSIX flag so you have shifted bases and are not on a posix compliant system. Your argument is a strawman since you scoped it to standards. Glibc broke a lot of applications in the wild with their 2012 change with a well intentioned but incorrect implementation. Even though the kernel supports many thousands of open files, glibc is behaving incorrectly. I will shift bases too and conveniently define a function called __fdelt_chk() to be sane and support the kernel limit of allowed files with no breakage. – Andrew Hacking Sep 11 '14 at 15:13
-
2@AndrewHacking: From the very first statement your comment is false. At this point I'm done arguing with you. – R.. GitHub STOP HELPING ICE Sep 11 '14 at 16:01
-
1@R.. I missed another one of your precious comments about scaling. I've implemented systems supporting over 20 million users logging on, at the same time, (as used by Cable&Wireless back in the 90's) so I know about scalability. The reason for the newer async API's is to avoid the overhead of both checking and transferring large fd sets between user and kernel space each iteration around the run loop. You increase your latency and throughput with select()/poll(), hence why newer apis were invented. I never said you can't service 100k fds but you will do it better with kqueue()/epoll()/aio. – Andrew Hacking Sep 11 '14 at 23:28
-
This won't work in a typical Unox implementation because FD_SETSIZE is limits the *numeric value* of the file descriptor. You cannot add file number 1030 to an fdset even if it would be the only element there (assuming FD_SETSIZE is 1024). – n. m. could be an AI Oct 23 '18 at 15:54
I also suggest using poll
if possible. And there exist several "event" processing libraries like libevent or libev (or the event abilities of Glib from GTK, or QtCore, etc) which should help you. There are also things like epoll. And your problem is related to C10k

- 223,805
- 18
- 296
- 547
-
1yes. i think this is the ultimate answer. If one of yours monitored descriptor falls over 1024 under linux, either you have to HACK through fd_set structure ( and risk further problems anyway ), or to use poll what is ... better. – philippe lhardy Dec 15 '13 at 21:11
-
And you have to pray that every library you use does it correctly. The only working solution to live with 1024 handles or to 100% understand your programs code including all libraries and make sure "select" is never used. – Lothar Nov 24 '19 at 15:14
It would be better (and easy) to replace with poll. Generally poll() is a simple drop-in replacement for select() and isn't limited by the 1024 of FD_SETSIZE...
fd_set fd_read;
int id = 42;
FD_ZERO(fd_read);
FD_SET(id, &fd_read);
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
if (select(id + 1, &fd_read, NULL, NULL, &tv) != 1) {
// Error.
}
becomes:
struct pollfd pfd_read;
int id = 42;
int timeout = 5000;
pfd_read.fd = id;
pfd_read.events = POLLIN;
if (poll(&pfd_read, 1, timeout) != 1) {
// Error
}
You need to include poll.h for the pollfd structure.
If you need to write as well as read then set the events flag as POLLIN | POLLOUT.

- 417
- 3
- 12
In order to use a fd_set
larger than FD_SETSIZE, it is possible to define an extended one like this :
#include <sys/select.h>
#include <stdio.h>
#define EXT_FD_SETSIZE 2048
typedef struct
{
long __fds_bits[EXT_FD_SETSIZE / 8 / sizeof(long)];
} ext_fd_set;
int main()
{
ext_fd_set fd;
int s;
printf("FD_SETSIZE:%d sizeof(fd):%ld\n", EXT_FD_SETSIZE, sizeof(fd));
FD_ZERO(&fd);
while ( ((s=dup(0)) != -1) && (s < EXT_FD_SETSIZE) )
{
FD_SET(s, &fd);
}
printf("select:%d\n", select(EXT_FD_SETSIZE,(fd_set*)&fd, NULL, NULL, NULL));
return 0;
}
This prints :
FD_SETSIZE:2048 sizeof(fd):256
select:2045
In order to open more than 1024 filedescriptors, it is needed to increase the limit using for instance
ulimit -n 2048
.
- 11,326
- 43
- 62
- 91
-
1This is potentially dangerous. Without entering in to the (valid, IMO) issue of standards compliance, there is a more obvious use case where this could fail, and that is when linking against a library compiled to use the system-defined FD_SETSIZE. Using `poll()` is the correct approach. – edam Jun 14 '16 at 13:44
Actually there IS a way to increase FD_SETSIZE
on Windows. It's defined in winsock.h
and per Microsoft themselves you can increase it by simply defining it BEFORE you include winsock.h
:
See Maximum Number of Sockets an Application Can Use (old link), or the more recent page Maximum Number of Sockets Supported.
I do it all the time and have had no problems. The largest value I have used was around 5000 for a server I was developing.
-
4BSD and Windows allows FD_SETSIZE to be set. Not Linux where fd_set internal size is in fact set by __FD_SETSIZE that is hardcoded to 1024. For linux, it is better to use poll since slecet can't work for more than first 1024 descriptors. in fact it can appear to work on linux but will use bits outside allocated fd_set, what for sure will corrupt stack and cause crashes. That's why current answer is to allocate yourself more place on stack what is not very pretty. – philippe lhardy Dec 15 '13 at 21:02
-
1
-
It's also mentioned here: https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-select (ctrl+f 'FD_SETSIZE') – Tom Jun 25 '21 at 12:12